Postgresql PSQLException:大对象不能在自动提交模式下使用

Postgresql PSQLException:大对象不能在自动提交模式下使用,postgresql,hibernate,jpa,wildfly,Postgresql,Hibernate,Jpa,Wildfly,我正在使用WildFly 10、JavaEE、JPA和Hibernate。最近我将我的应用程序从MySQL迁移到PostgreSQL。在使用MySQL时,我会使用以下方法在实体中存储图像: @Lob @Basic(fetch = FetchType.LAZY) private byte[] image; 这非常有效,MySQL使用了LONGBLOB来存储数据 切换到PostgreSQL后,列类型为OID,我在保存图像时收到此错误: Caused by: org.postgresql.util.

我正在使用WildFly 10、JavaEE、JPA和Hibernate。最近我将我的应用程序从MySQL迁移到PostgreSQL。在使用MySQL时,我会使用以下方法在实体中存储图像:

@Lob
@Basic(fetch = FetchType.LAZY)
private byte[] image;
这非常有效,MySQL使用了
LONGBLOB
来存储数据

切换到PostgreSQL后,列类型为
OID
,我在保存图像时收到此错误:

Caused by: org.postgresql.util.PSQLException: Large Objects may not be used in auto-commit mode.
at org.postgresql.largeobject.LargeObjectManager.createLO(LargeObjectManager.java:308)
at org.postgresql.largeobject.LargeObjectManager.createLO(LargeObjectManager.java:296)
at org.postgresql.jdbc.PgPreparedStatement.createBlob(PgPreparedStatement.java:1202)
at org.postgresql.jdbc.PgPreparedStatement.setBlob(PgPreparedStatement.java:1243)
at org.jboss.jca.adapters.jdbc.WrappedPreparedStatement.setBlob(WrappedPreparedStatement.java:1157)
at org.hibernate.type.descriptor.sql.BlobTypeDescriptor$4$1.doBind(BlobTypeDescriptor.java:112)
at org.hibernate.type.descriptor.sql.BasicBinder.bind(BasicBinder.java:73)
at org.hibernate.type.AbstractStandardBasicType.nullSafeSet(AbstractStandardBasicType.java:257)
at org.hibernate.type.AbstractStandardBasicType.nullSafeSet(AbstractStandardBasicType.java:252)
at org.hibernate.type.AbstractSingleColumnStandardBasicType.nullSafeSet(AbstractSingleColumnStandardBasicType.java:39)
at org.hibernate.persister.entity.AbstractEntityPersister.dehydrate(AbstractEntityPersister.java:2598)
at org.hibernate.persister.entity.AbstractEntityPersister.insert(AbstractEntityPersister.java:2883)
... 131 more
我以这种方式插入:

@PersistenceContext
EntityManager entityManager;

...

//Simple insert method...
this.entityManager.persist(entity);
这是我的
persistence.xml

<persistence version="2.1" xmlns="http://xmlns.jcp.org/xml/ns/persistence"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence http://xmlns.jcp.org/xml/ns/persistence/persistence_2_1.xsd">
    <persistence-unit name="MyApp" transaction-type="JTA">
        <jta-data-source>java:jboss/datasources/PostgreSQLDS</jta-data-source>
        <shared-cache-mode>DISABLE_SELECTIVE</shared-cache-mode>
        <properties>
            <property name="hibernate.enable_lazy_load_no_trans" value="true"/>
            <property name="hibernate.cache.use_second_level_cache"
                      value="true"/>
            <property name="hibernate.cache.use_query_cache" value="true"/>
        </properties>
    </persistence-unit>
</persistence>
…也没什么作用


我完全不明白这为什么行不通。看起来这似乎不是一个非常常见的例外,我觉得我正在以完全错误的方式来完成存储图像数据的任务。我能做些什么来解决这个问题,或者我应该如何存储数据?

我不能告诉您在Hibernate中是如何完成的,但是打开和读取/写入大型对象必须在同一个数据库事务中进行

禁用自动提交模式应该可以,也许你做错了什么

但我可以建议您不要使用大型物体吗?

通常使用
bytea
PostgreSQL数据类型要容易得多,它可以包含高达1GB的数据。除非您以块的形式存储和检索数据,否则大型对象不会提供任何优势,而且我怀疑您是否能够通过ORM充分利用大型对象功能。

我遇到了同样的问题,并通过更改JBOSS配置文件(standalone.xml或domain.xml)解决了这个问题

首先分析这个问题,通过日志记录,我发现自动提交仍然是正确的

entityManager.unwrap(SessionImpl.class).connection().getAutoCommit()
我试着用

entityManager.unwrap(SessionImpl.class).connection().setAutoCommit(false)
但这导致了异常“您无法在托管事务期间设置自动提交”

在研究异常消息时,我发现这解释了为什么自动提交总是正确的

我们使用的数据源配置如下:

<datasource jta="true"  . . . >

“我觉得我正在以完全错误的方式存储图像数据。”正确。图像不应位于数据库中all@e4c5就我而言,我看不到其他选择。此应用程序将跨多个不同的WildFly安装水平扩展。如果我将映像存储在本地磁盘上,则并非所有用户都可以访问。我知道的唯一方法就是使用数据库来解决这个问题。每个映像的大小不超过1MB。您不必存储在本地磁盘上。您可以存储在S3、Google文件或任意数量的CDN上。您将获得巨大的性能提升,“创建一个仅用于存储数据的实体并使用@OneToOne关系”,这是一种常见的解决方法,可以在Hibernate中实现“属性”级别的延迟加载。如果你正在使用JPA,你可以尝试一个不同的JPA实现,它支持适当的惰性加载。虽然这不能解决这个异常,但它目前是我最容易的替代解决方案。使用
bytea
并删除
@Lob
注释效果良好。
<datasource jta="true"  . . . >
<xa-datasource . . . .>
max_prepared_transactions = 500     # zero disables the feature