Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/hibernate/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 大对象不能在自动提交模式下使用_Java_Hibernate_Postgresql_Jpa_Autocommit - Fatal编程技术网

Java 大对象不能在自动提交模式下使用

Java 大对象不能在自动提交模式下使用,java,hibernate,postgresql,jpa,autocommit,Java,Hibernate,Postgresql,Jpa,Autocommit,我有一个Spring应用程序,它在PostgreSQL数据库上使用Hibernate。我正在尝试将文件存储在数据库的表中。它似乎将行与文件一起存储(我只是在EntityManager上使用persist方法),但当从数据库加载对象时,会出现以下异常: org.postgresql.util.PSQLException: Large Objects may not be used in auto-commit mode. 为了加载数据,我使用了一个MultipartFile transient

我有一个Spring应用程序,它在PostgreSQL数据库上使用Hibernate。我正在尝试将文件存储在数据库的表中。它似乎将行与文件一起存储(我只是在EntityManager上使用persist方法),但当从数据库加载对象时,会出现以下异常:

org.postgresql.util.PSQLException: Large Objects may not be used in auto-commit mode.
为了加载数据,我使用了一个MultipartFile transient atribute,并在其setter中设置了我想要保存的信息(byte[],fileName,size)。 我要持久化的实体看起来像这样(我已经编写了其余的getter/setter):

我可以看到,当它被持久化时,我的行中有数据,但当我调用此方法时,它失败了:

public List<MyClass> findByDescription(String text) {
    Query query = getEntityManager().createQuery("from MyClass WHERE UPPER(description) like :query ORDER BY creationDate DESC");
    query.setParameter("query", "%" + text.toUpperCase() + "%");
    return query.getResultList();
}
公共列表findByDescription(字符串文本){
Query Query=getEntityManager().createQuery(“来自MyClass,上面的(描述)类似于:creationDate DESC的查询顺序”);
query.setParameter(“query”、“%”+text.toUpperCase()+“%”);
返回query.getResultList();
}
仅当结果包含包含文件的对象时,此方法才会失败。我已尝试在persistence.xml中设置

<property name="hibernate.connection.autocommit" value="false" />

但这并不能解决问题

一般来说,应用程序工作得很好,它只在事务完成时提交数据,如果出现故障,它会执行回滚,所以我不明白为什么会发生这种情况

有什么想法吗

谢谢

更新

查看Shekhar给出的链接,建议将调用包含在事务中,因此我在事务中设置了服务调用,它可以正常工作(我添加了@Transactional注释)

@Transactional
公共列表查找(字符串文本){
返回myClassDAO.findByDescription(text);
}
问题是我不想保留任何数据,所以我不明白为什么应该将其包含在事务中。当我只从数据库中加载了一些数据时,进行提交有意义吗


谢谢。

一个大对象可以存储在多个记录中,这就是为什么您必须使用事务。所有记录都是正确的,或者根本没有记录


除非您需要存储大于1GB的文件,否则我建议您使用bytea作为数据类型,而不是大型对象


bytea基本上就是其他数据库(如Oracle)中的BLOB,它的处理与JDBC兼容得多

如果可以,例如,在MyClass和file属性之间创建一个中间实体。 比如:

@Entity
@Table(name="myobjects")
public class MyClass {
    @OneToOne(cascade = ALL, fetch = LAZY)
    private File file;
}

@Entity
@Table(name="file")
public class File {
     @Lob
     byte[] file;
}

您不能使用@Lob和fetch类型Lazy。它不起作用。您必须有一个中间类。

我没有使用
@Transactional
,而是将PostgreSQL数据库中的此列从
oid
类型更新为
bytea
类型,并为
@Lob
字段添加了
@type

i、 e

改变

@Lob
private byte[] image;


您应该检查连接上的方法是否真的将自动提交设置为false

就我而言

<property name="hibernate.connection.autocommit" value="false" />

不起作用,因为我的数据库连接类型要求自动提交为true


在我的例子中,问题在于JBoss配置。我使用的是JTA数据源,这导致了问题。使用XA数据源,它工作得很好。有关更多详细信息,请参阅。

在存储库界面上使用
@Transactional

如果不想保留数据,为什么要映射
文件?是不是应该是
@Transient
?@matt b我想保存文件,但只保存在保存操作中,而不保存在读取操作中。这就是我不明白读取应该在事务中的原因。在保存对象时,不能只使用@Transactional。通常需要一个事务来访问数据库(无论是读还是写)。在此异常之后,hibernate无法连接数据库抛出:
原因:org.hibernate.hibernate异常:无法访问lob流
,是否有任何数据库命令或东西来恢复此数据库?我不太确定这是如何回答原始问题的?原始海报不希望在没有事务的情况下写入Lob,他希望在没有事务的情况下读取Lob。默认情况下,Lob是惰性加载的,加载应该在加载父对象的同一事务中进行。这是如何回答的?如果不需要在每个查询中检索Lob,那么这是最好的方法。这会带来一些开销,因为在访问对象时需要调度一个额外的查询,但在某些情况下,这是理想的。你是一个救生员!添加@Type注释对我来说已经足够了,谢谢!这应该是正确的答案!您所需要做的就是定义LOB的hibernate类型,惰性获取工作正常。我打算存储一个非常大的字符串,并通过使用org.hibernate.type.StringType解决了这个问题。这个解决方案在我的案例中返回了一个空结果。这非常有效,谢谢!
ALTER TABLE person DROP COLUMN image;
ALTER TABLE person ADD COLUMN image bytea;
@Lob
private byte[] image;
@Lob
@Type(type = "org.hibernate.type.ImageType")
private byte[] image;
<property name="hibernate.connection.autocommit" value="false" />