Java Spring、Hibernate、Blob延迟加载

Java Spring、Hibernate、Blob延迟加载,java,mysql,hibernate,lazy-loading,blob,Java,Mysql,Hibernate,Lazy Loading,Blob,我需要帮助在Hibernate中加载惰性blob。 我的web应用程序中有以下服务器和框架:MySQL、Tomcat、Spring和Hibernate 数据库配置的一部分 <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource" destroy-method="close"> <property name="user" value="${jdbc.username}"/>

我需要帮助在Hibernate中加载惰性blob。 我的web应用程序中有以下服务器和框架:MySQL、Tomcat、Spring和Hibernate

数据库配置的一部分

<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource" destroy-method="close">
    <property name="user" value="${jdbc.username}"/>
    <property name="password" value="${jdbc.password}"/>
    <property name="driverClass" value="${jdbc.driverClassName}"/>
    <property name="jdbcUrl" value="${jdbc.url}"/>

    <property name="initialPoolSize">
        <value>${jdbc.initialPoolSize}</value>
    </property>
    <property name="minPoolSize">
        <value>${jdbc.minPoolSize}</value>
    </property>
    <property name="maxPoolSize">
        <value>${jdbc.maxPoolSize}</value>
    </property>
    <property name="acquireRetryAttempts">
        <value>${jdbc.acquireRetryAttempts}</value>
    </property>
    <property name="acquireIncrement">
        <value>${jdbc.acquireIncrement}</value>
    </property>
    <property name="idleConnectionTestPeriod">
        <value>${jdbc.idleConnectionTestPeriod}</value>
    </property>
    <property name="maxIdleTime">
        <value>${jdbc.maxIdleTime}</value>
    </property>
    <property name="maxConnectionAge">
        <value>${jdbc.maxConnectionAge}</value>
    </property>
    <property name="preferredTestQuery">
        <value>${jdbc.preferredTestQuery}</value>
    </property>
    <property name="testConnectionOnCheckin">
        <value>${jdbc.testConnectionOnCheckin}</value>
    </property>
</bean>


<bean id="lobHandler" class="org.springframework.jdbc.support.lob.DefaultLobHandler" />

<bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
    <property name="dataSource" ref="dataSource" />
    <property name="configLocation" value="/WEB-INF/hibernate.cfg.xml" />
    <property name="configurationClass" value="org.hibernate.cfg.AnnotationConfiguration" />
    <property name="hibernateProperties">
        <props>
            <prop key="hibernate.dialect">${hibernate.dialect}</prop>
        </props>
    </property>
    <property name="lobHandler" ref="lobHandler" />
</bean>

<tx:annotation-driven transaction-manager="txManager" />

<bean id="txManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
    <property name="sessionFactory" ref="sessionFactory" />
</bean>
问题描述。我试图在网页上显示与文件相关的数据库记录,这些记录保存在MySQL数据库中。如果数据量很小,所有这些都可以正常工作。但是数据量很大,我收到一个错误
java.lang.OutOfMemoryError:java堆空间


我尝试在表的每一行上写入blobFields空值。在这种情况下,应用程序工作正常,内存不会耗尽。我的结论是,标记为lazy(
@Basic(fetch=FetchType.lazy)
)的blob字段实际上不是lazy

我建议您使用继承来处理此场景。有一个没有blob的基类和一个包含字节数组的派生类。只有在需要在UI上显示blob时,才能使用派生类。

我很困惑。Emmanuel Bernard在文章中写道,默认情况下,
@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上进行了测试,因此它应该适用于u

惰性属性加载需要构建时字节码检测


若要避免字节码插装,一个选项是创建两个使用相同表的实体,一个带有blob,另一个不带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添加了插件:

        <plugin>
            <groupId>org.hibernate.orm.tooling</groupId>
            <artifactId>hibernate-enhance-maven-plugin</artifactId>
            <executions>
                <execution>
                    <phase>compile</phase>
                    <configuration>
                        <failOnError>true</failOnError>
                        <enableLazyInitialization>true</enableLazyInitialization>
                    </configuration>
                    <goals>
                        <goal>enhance</goal>
                    </goals>
                </execution>
            </executions>
        </plugin>

org.hibernate.orm.tooling
hibernate增强maven插件
编译
真的
真的
增强

对于我来说,延迟加载只通过编译并运行它来工作,例如,在eclipse或intellij上不起作用

我正在使用gradle,然后我做了以下操作来让它工作

  • 注释实体
  • 安装Hibernate gradle插件
格雷德尔先生

buildscript {
    repositories {
        mavenCentral()
    }
    dependencies {
        classpath "org.hibernate:hibernate-gradle-plugin:5.4.0.Final"
    }
}

apply plugin: 'java'
apply plugin: 'application'
apply plugin: 'org.hibernate.orm'
hibernate {
    enhance {
        enableLazyInitialization = true
        enableDirtyTracking = true
        enableAssociationManagement = true
    }
}
Entity.java

@Entity
public class Person {

    @Id
    @GeneratedValue
    private Integer id;

    @Lob
    @Basic(fetch = FetchType.LAZY)
    @Column(length = 255, nullable = false)
    private String name;
测试

./gradlew run

谢谢你,达林。但是我想知道为什么懒惰的领域没有我想要的那么懒惰:)但是,当然,如果我没有找到另一种解决问题的方法,我会用你的建议。谢谢你,帕斯卡。我不明白如何指定与父类的一对一映射。你介意帮我吗?再次感谢您。父类@OneToOne(cascade=CascadeType.ALL,fetch=FetchType.LAZY)私有文件blobbean FileBlobBean;子类:@Id@GeneratedValue(strategy=GenerationType.IDENTITY)@Basic(optional=false)@Column(name=“Uid”,nullable=false)私有长Uid@Lob@Basic(fetch=FetchType.LAZY)@Column(name=“BlobField”,columnDefinition=“LONGBLOB”)私有字节[]BlobField@OneToOne(mappedBy=“fileBlobBean”)@JoinColumn(name=“Uid”,referencedColumnName=“Uid”,nullable=false)公共FileBean FileBean;Hibernate在表“文件”中创建了一个新字段。田野里空无一人。我做错了什么?另外,我为糟糕的代码格式感到抱歉。对我来说,这很有帮助:父项:@OneToOne(cascade=CascadeType.ALL,fetch=FetchType.LAZY)@PrimaryKeyJoinColumn私有文件blobbean。。。孩子:只有id,没有提及父母。你能告诉我如何实现blob的一对一关系吗?看,我也没用。Hibernate 4.3.1。甲骨文10g-XE。您可能已经实现了字节码插装吗?PrimitiveByteArrayBlobType已被弃用,使用MaterializedBlobType重新计算,并且对我也不起作用(hibernate 5.0.7.Final,postgresql)
pom.xml
条目具体做什么?
./gradlew run