休眠延迟加载不适用于多对一映射

Posted

技术标签:

【中文标题】休眠延迟加载不适用于多对一映射【英文标题】:Hibernate lazy loading not work with many-to-one mapping 【发布时间】:2014-11-13 00:34:39 【问题描述】:

我的多对一映射存在性能问题。当我在日志文件中调试 SQL 查询时,主体查询没问题,但是在我有其他表示多对一对象映射的查询之后。

Entity.hbm.xml:

<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
    "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
    "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd" >

<hibernate-mapping>
    <class name="com.omb.database.mapping.MyEntity" table="MY_ENTITY">
        <id name="id" type="java.lang.Integer">
            <column name="ENTITY_ID"/>
            <generator class="sequence">
                <param name="sequence">SEQ_MY_ENTITY</param>
            </generator>
        </id>

        <property name="prop1" type="string" column="PROP1" />
        <many-to-one name="object1" column="OBJECT1_ID" class="com.omb.database.mapping.Object1" />
        <many-to-one name="object2" column="OBJECT2_ID" class="com.omb.database.mapping.Object2" /> 

    </class>
</hibernate-mapping>

Object1.hbm.xml:

<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
    "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
    "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd" >

<hibernate-mapping default-lazy="true">

    <class name="com.omb.database.mapping.Object1" table="TABLE_OBJECT_1">
        <id name="id" type="java.lang.Integer" column="OBJECT1_ID" />
        <property name="label" type="string" column="LABEL_OBJECT_1" length="15" />
    </class>

</hibernate-mapping>

Object2.hbm.xml:

<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
    "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
    "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd" >

<hibernate-mapping default-lazy="true">

    <class name="com.omb.database.mapping.Object2" table="TABLE_OBJECT_2">
        <id name="id" type="java.lang.Integer" column="OBJECT2_ID" />
        <property name="label" type="string" column="LABEL_OBJECT_2" length="15" />
    </class>

</hibernate-mapping>

查询 HBM:

public List<Entity> findByObject1Id(Integer object1Id) throws DataAccesException 

        List<Entity> results = null;
        try 
            Query query = this.getSession().createQuery(
                    "from Entity ent where ent.object1.id = :object1Id");
            query.setParameter("object1Id", object1Id);
            results = query.list();
         catch (HibernateException hbe) 
            throw new DataAccesException(hbe);
        

        return results;
    

在 pom.xml 中

<!-- Hibernate 3 -->
        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate</artifactId>
            <version>3.2.6.ga</version>
            <exclusions>
                <exclusion>
                    <groupId>javax.transaction</groupId>
                    <artifactId>jta</artifactId>
                </exclusion>
                <exclusion>
                    <groupId>net.sf.ehcache</groupId>
                    <artifactId>ehcache</artifactId>
                </exclusion>
                <exclusion>
                    <groupId>asm</groupId>
                    <artifactId>asm-attrs</artifactId>
                </exclusion>
            </exclusions>
        </dependency>

【问题讨论】:

请显示您看到的查询并说明您的确切问题。您是在问为什么会看到这些查询?您是否在问如何更改代码/配置以某种方式更改查询? 【参考方案1】:

您是否尝试过使用 FetchMode.SELECT,像这样;

<many-to-one name="object1" column="OBJECT1_ID" class="com.omb.database.mapping.Object1" fetch="select" />

【讨论】:

lazy="true" 和 fetch="select" 有什么区别? @OusmaneMINTE 检查此线程; ***.com/questions/4374528/…【参考方案2】:

您的映射似乎没问题。如此处所述5.1.1. Entity

&lt;class&gt; 属性 lazy 默认为 true

lazy(可选):可以通过设置lazy="false"来禁用延迟获取。

&lt;many-to-one&gt; 相同:5.1.7.1. Using a foreign key or an association table lazy 属性:

lazy(可选 - 默认为代理):默认情况下,单点关联被代理。 lazy="no-proxy" 指定在第一次访问实例变量时应该延迟获取属性。这需要构建时字节码检测。 lazy="false" 指定将始终急切地获取关联。

那么,问题出在哪里?

我会在你的调试窗口中说。因为您确实有对列表的引用,并且您正在观察结果 - 在它执行的那一刻 - 引用也被加载。懒惰 - 但加载。这实际上就是我们想要的。代理 - 首次启用时 - 正在强制加载。

尝试将其从手表中删除。或关闭会话,然后将其放入手表中...您应该看到,上面使用的查询 - 没有加载引用...仅在真正访问时...即使通过调试窗口

【讨论】:

感谢您的帮助。这是我的错...如果我没有使用映射对象的方法 hashCode() 或 equals(),我查看了 MyEntity 类,但是我忘记了将 Hibernate 对象转换为 Pojo 对象以用于我的表示层的转换服务... . 在这部分中,我执行 myEntity.getObject1 () 和 myEntity.getObject2 () .. 对帖子表示抱歉! 如果我的回答对你有帮助 - 很好。如果你有你的答案 - 太好了! ;) 享受强大的休眠 ;)

以上是关于休眠延迟加载不适用于多对一映射的主要内容,如果未能解决你的问题,请参考以下文章

休眠延迟加载不适用于 Spring Boot => 无法延迟初始化角色集合无法初始化代理 - 无会话

Mybatis学习笔记—高级映射,延迟加载

如何在休眠/弹簧中更新多对多集合(延迟加载)?

MyBatis一对多查询及延迟加载

Mybatis延迟加载缓存逆向工程

解决hibernate中的懒加载(延迟加载)问题