web-dev-qa-db-ja.com

Hibernateの遅延読み込みは多対1のマッピングでは機能しません

多対1のマッピングでパフォーマンスの問題があります。ログファイルでSQLクエリをデバッグすると、プリンシパルクエリは問題ありませんが、多対1のオブジェクトマッピングを表す他のクエリができた後です。

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>
8
Ousmane MINTE

このように、FetchMode.SELECTを試してみましたか。

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

マッピングは問題ないようです。ここに記載されているように 5.1.1。エンティティ

<class>属性lazyはデフォルトでtrueです

  • lazy(オプション):lazy = "false"を設定すると、遅延フェッチを無効にできます。

<many-to-one>についても同じです: 5.1.7.1。外部キーまたは関連付けテーブルの使用lazy属性:

  • レイジー(オプション-デフォルトはプロキシ):デフォルトでは、シングルポイントの関連付けがプロキシされます。 lazy="no-proxy"は、インスタンス変数が最初にアクセスされたときにプロパティを遅延フェッチする必要があることを指定します。これには、ビルド時のバイトコードインストルメンテーションが必要です。 lazy="false"は、関連付けが常に熱心にフェッチされることを指定します。

それで、問題はどこにありますか?

私はあなたのデバッグウィンドウで言うでしょう。リストへの参照があり、結果を監視しているため(実行された瞬間)、参照も読み込まれます。怠惰に-しかしロードされました。それが実際に私たちが望んでいることです。プロキシ(最初にtuchedされたとき)がロードを強制しています。

時計から取り外してみてください。または、セッションを閉じてからウォッチに入れます...上記で使用したクエリは参照をロードしていません...実際にアクセスした場合のみ...デバッグウィンドウ経由でも

3
Radim Köhler