Spring,Hibernate,Blob懒加载

我在Hibernate中需要有关延迟blob加载的帮助。 我在我的Web应用程序中有这些服务器和框架:MySQL,Tomcat,Spring和Hibernate。

数据库配置的一部分。

      ${jdbc.initialPoolSize}   ${jdbc.minPoolSize}   ${jdbc.maxPoolSize}   ${jdbc.acquireRetryAttempts}   ${jdbc.acquireIncrement}   ${jdbc.idleConnectionTestPeriod}   ${jdbc.maxIdleTime}   ${jdbc.maxConnectionAge}   ${jdbc.preferredTestQuery}   ${jdbc.testConnectionOnCheckin}          ${hibernate.dialect}         

实体类的一部分

 @Lob @Basic(fetch=FetchType.LAZY) @Column(name = "BlobField", columnDefinition = "LONGBLOB") @Type(type = "org.springframework.orm.hibernate3.support.BlobByteArrayType") private byte[] blobField; 

问题描述。 我正在尝试在网页上显示与文件相关的数据库记录,这些记录保存在MySQL数据库中。 如果数据量很小,一切正常。 但是数据量很大我收到了一个错误java.lang.OutOfMemoryError: Java heap space我试图在每行表的blobFields中写入值。 在这种情况下,应用程序工作正常,内存不会消失。 我得出结论,标记为懒惰的blob字段@Basic(fetch=FetchType.LAZY) )实际上并不是懒惰的!

我很困惑。 Emmanuel Bernard在ANN-418中写道, @Basic(fetch = FetchType.LAZY)默认是懒惰的(即你甚至不需要使用@Lob @Basic(fetch = FetchType.LAZY)注释)。

一些用户报告说,延迟加载@Lob 不适用于所有驱动程序/数据库 。

有些用户报告说它在使用字节码检测时起作用(javassit?cglib?)。

但是我在文档中找不到任何明确的参考。

最后, 建议的解决方法是使用“假”一对一映射而不是属性。 从现有类中删除LOB字段,创建引用同一个表的新类,相同的主键以及仅作为属性的必要LOB字段。 将映射指定为一对一,fetch =“select”,lazy =“true”。 只要你的父对象仍然在你的会话中,你应该得到你想要的。 (只需将其转换为注释)。

当然,您可以提取该值并将其放入具有惰性“@OneToOne”关系的新表中,但是在我们的应用程序中,只需使用此配置即可轻松地按需加载LOB

 @Lob @Fetch(FetchMode.SELECT) @Type(type="org.hibernate.type.PrimitiveByteArrayBlobType") byte[] myBlob; 

这在我们的项目中同时在PostgreSQL,MySQL,SQLServer和Oracle上进行了测试,所以它应该适用于你

我建议你使用inheritance来处理这种情况。 有一个没有blob的基类和一个包含字节数组的派生类。 仅当需要在UI上显示blob时才使用派生类。

延迟属性加载需要构建时字节码检测。

Hibernate docs:使用lazy属性获取

如果你想避免使用字节码检测,一个选项就是创建两个使用相同表的实体,一个不带blob的实体。 然后在需要blob时仅使用带有blob的实体。

我有同样的问题,这是我的修复:

我的实体:

 @Entity @Table(name = "file") public class FileEntity { @Id @GeneratedValue private UUID id; @NotNull private String filename; @NotNull @Lob @Basic(fetch = FetchType.LAZY) private byte[] content; ... 

在pom.xml中添加了插件:

   org.hibernate.orm.tooling hibernate-enhance-maven-plugin   compile  true true   enhance