大对象可能无法在自动提交模式下使用

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

org.postgresql.util.PSQLException: Large Objects may not be used in auto-commit mode. 

要加载数据,我正在使用MultipartFile瞬态属性,并在其setter中设置我想要保留的信息(byte [],fileName,size)。 我坚持的实体看起来像这个(我已经省略了其余的getter / setter):

 @Entity @Table(name="myobjects") public class MyClass { @Id @GeneratedValue(strategy=GenerationType.SEQUENCE, generator="sequence") @SequenceGenerator(name="sequence", sequenceName="myobjects_pk_seq", allocationSize=1) @Column(name="id") private Integer id; @Lob private String description; @Temporal(TemporalType.TIMESTAMP) private Date creationDate; @Transient private MultipartFile multipartFile; @Lob @Basic(fetch=FetchType.LAZY, optional=true) byte[] file; String fileName; String fileContentType; Integer fileSize; public void setMultipartFile(MultipartFile multipartFile) { this.multipartFile = multipartFile; try { this.file = this.multipartFile.getBytes(); this.fileName = this.multipartFile.getOriginalFilename(); this.fileContentType = this.multipartFile.getContentType(); this.fileSize = ((Long) this.multipartFile.getSize()).intValue(); } catch (IOException e) { logger.error(e.getStackTrace()); } } } 

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

 public List 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(); } 

仅当结果包含具有文件的对象时,此方法才会失败。 我试着在我的persistence.xml中设置

  

但它没有解决问题。

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

任何想法?

谢谢。

UPDATE

看看Shekhar给出的链接,建议将调用包含在一个转换中,所以我在一个事务中设置了服务调用它是否正常工作(我添加了@Transactional注释)。

 @Transactional public List find(String text) { return myClassDAO.findByDescription(text); } 

问题是我不想保留任何数据,所以我不明白为什么它应该包含在一个事务中。 当我只从数据库中加载一些数据时,提交是否有意义?

谢谢。

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

https://www.postgresql.org/docs/current/static/largeobjects.html

如果可以,请在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并获取类型Lazy。 它不起作用。 你必须有一个中级class。

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

bytea基本上是BLOB在其他数据库(例如Oracle)中的地方,它的处理与JDBC更加兼容。