2

私はそれぞれ1..nの記事を持っている1..nのメンバーがいるフォーラムを持っているので、これは私のマッピングです:

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

<hibernate-mapping auto-import="true">
   <class name="Forum" table="forum">
      <id name="id">
         <generator class="identity" />
      </id>
      <property name="name" />
      <set name="members" table="members" inverse="true">
         <key column="forum_id" not-null="true" />
         <one-to-many class="Member" />
      </set>
   </class>
   <class name="Article" table="article">
      <id name="id">
         <generator class="identity" />
      </id>
      <property name="title" />

      <many-to-one name="member" column="member_id" class="Member"
         not-null="true">
      </many-to-one>
   </class>
   <class name="Member" table="member">
      <id name="id">
         <generator class="identity" />
      </id>
      <property name="name" />

      <many-to-one name="forum" column="forum_id" class="Forum"
         not-null="true">
      </many-to-one>

      <set name="articles" fetch="join" table="articles"
         inverse="true">
         <key column="member_id" not-null="true" />
         <one-to-many class="Article" />
      </set>
   </class>
</hibernate-mapping>

今私は2つのテストがあります:

これはLazyInitializationExceptionで失敗します:

 public void testFetchJoinByIteratorNavigation ( )
   {
      Forum forum = (Forum) repository.findById(Forum.class, forumId);
      Member member = forum.getMembers().iterator().next();
      assertEquals(member.getName(), "firstMember");
      endTransaction();
      assertEquals(1, member.getArticles().size());
   }

これは成功します:

 public void testFetchJoinByGraphNavigation ( )
   {
      Member member = (Member) repository.findById(Member.class, memberId);
      assertEquals(member.getName(), "firstMember");
      endTransaction();
      assertEquals(1, member.getArticles().size());
  }

唯一の違いは、メンバーをロードする方法です。

Hibernateリファレンスは次のように述べています。

「マッピングドキュメントで定義されているフェッチ戦略は、以下に影響します。

  1. get()またはload()による取得
  2. アソシエーションがナビゲートされたときに暗黙的に発生する取得
  3. 基準クエリ
  4. 副選択フェッチが使用されている場合のHQLクエリ」

後続のテストはケース1です。(get()またはload()による取得)失敗したテストはケース2です。IMHO

「forum.getMembers()。iterator()。next()」がメンバーのすべての記事をロードしないのはなぜですか?

編集1:

これは私のリポジトリです:

package hibernate.fetch;
import org.springframework.orm.hibernate3.support.HibernateDaoSupport;

public class Repository extends HibernateDaoSupport
{
    public Object findById ( Class clazz, Long objectId )
    {
        return getHibernateTemplate().load(clazz, objectId);
    }

    public void save ( Object object )
    {
        getHibernateTemplate().saveOrUpdate(object);
    }
}

これは私のpom.xmlです:

<?xml version="1.0" encoding="UTF-8"?>
<project>
    <modelVersion>4.0.0</modelVersion>
    <groupId>hibernate-fetch</groupId>
    <artifactId>hibernate-fetch</artifactId>
    <version>1.0-SNAPSHOT</version>
    <build>
        <plugins>
            <plugin>
                <artifactId>maven-compiler-plugin</artifactId>
                <configuration>
                    <source>1.5</source>
                    <target>1.5</target>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-eclipse-plugin</artifactId>
                <configuration>
                    <downloadSources>true</downloadSources>
                    <ajdtVersion>1.5</ajdtVersion>
                </configuration>
            </plugin>
        </plugins>
    </build>
    <dependencies>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring</artifactId>
            <version>2.5.6</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-orm</artifactId>
            <version>2.5.6</version>
        </dependency>
        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-core</artifactId>
            <version>3.3.1.GA</version>
        </dependency>
        <dependency>
            <groupId>log4j</groupId>
            <artifactId>log4j</artifactId>
            <version>1.2.14</version>
        </dependency>
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-log4j12</artifactId>
            <version>1.5.2</version>
        </dependency>
        <dependency>
            <groupId>javassist</groupId>
            <artifactId>javassist</artifactId>
            <version>3.8.0.GA</version>
        </dependency>
        <dependency>
            <groupId>postgresql</groupId>
            <artifactId>postgresql</artifactId>
            <version>8.2-504.jdbc3</version>
        </dependency>
        <dependency>
            <groupId>log4j</groupId>
            <artifactId>log4j</artifactId>
            <version>1.2.13</version>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>3.8.1</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-test</artifactId>
            <version>2.5.6</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>jmock</groupId>
            <artifactId>jmock</artifactId>
            <version>1.1.0</version>
            <scope>test</scope>
        </dependency>
    </dependencies>
</project>

編集2: これは私のテストケースです:

package hibernate.fetch;

import org.springframework.test.AbstractTransactionalSpringContextTests;

public class ForumTest extends AbstractTransactionalSpringContextTests
{
    private Repository  repository;
    private Long        memberId;
    private Long        forumId;
    private String      name    = "test";

    @Override
    protected String[] getConfigLocations ( )
    {
        return new String[] { "applicationContext.xml" };
    }

    @Override
    protected void onSetUpBeforeTransaction ( ) throws Exception
    {
        System.out.println(">> preparing Test");
        Forum forum = new Forum();
        forum.setName(name);
        repository.save(forum);
        forumId = forum.getId();

        Member member = new Member();
        member.setName(name);
        forum.addMember(member);
        repository.save(member);
        memberId = member.getId();

        Article article = new Article();
        article.setTitle(name);
        member.addArticle(article);

        repository.save(article);

        super.onSetUpBeforeTransaction();
        System.out.println(">> Test prepared");
    }

    public void testFetchJoinByGraphNavigation ( )
    {
        System.out.println(">> testFetchJoinByGraphNavigation");
        Member member = (Member) repository.findById(Member.class, memberId);
        assertEquals(member.getName(), name);
        endTransaction();
        assertEquals(1, member.getArticles().size());
    }

    public void testFetchJoinByIteratorNavigation ( )
    {
        System.out.println(">> testFetchJoinByIterationNavigation");
        Forum forum = (Forum) repository.findById(Forum.class, forumId);
        Member member = forum.getMembers().iterator().next();
        assertEquals(member.getName(), name);
        endTransaction();
        // throws LazyInitializationException because articles were NOT loaded
        assertEquals(1, member.getArticles().size());
    }

    public Repository getRepository ( )
    {
        return repository;
    }

    public void setRepository ( Repository repository )
    {
        this.repository = repository;

}

}

よくわかりません!

4

3 に答える 3

1

この 2 つのケースは、実際にはまったく異なります。

失敗した例では、遅延初期化された Member エンティティのコレクションを持つ Forum エンティティを読み込んでいます。コレクションをナビゲートしようとすると、コレクションが遅延コレクションであり、セッションが閉じられる前にコレクションをロードしなかったために失敗します。

実際の例では、これは「グラフ ナビゲーション」ではなく、Member エンティティを直接読み込んでいるため、遅延読み込みのセマンティクスは含まれていません。

あなたが参照しているドキュメントには、最初のケースの言い回しのさまざまな方法が含まれていました。メンバーのセットで熱心な読み込みを指定すると、失敗が防止されます。

于 2009-09-21T17:36:53.120 に答える
0

findById(...) メソッドで HQL を使用していますか? HQL を使用する場合、Hibernate はフェッチ/結合の設定を考慮しません。アソシエーションを熱心にロードするには、「left join fetch」のような HQL 句を使用する必要があります。また、Hibernate 2.x を使用している場合、単一のクエリで複数のコレクションを熱心にフェッチすることはできません。hibernate Web サイトの Advanced Problems FAQ を参照してください。

https://www.hibernate.org/117.html#A13

于 2009-09-21T22:57:24.337 に答える
-1

休止状態のドキュメントのバグだと思います。

リファレンス ドキュメントには次のように書かれています。

「一方で、本質的に遅延の少ない結合フェッチを使用できます」

JPwHの本では、p。579

したがって、fetch="join" は遅延読み込みを無効にします。

それは本当ではない。記事のマッピングを次のように変更すると

<set name="articles" fetch="join" lazy="false" table="articles" inverse="true">

両方のテストは正常に実行されますが、2 番目のテストではメンバーのロード時に結合が実行されません!

したがって、私の結論:結合戦略を使用した熱心なフェッチは、プロキシの初期化に影響を与えず、遅延読み込みを無効にしません。これは、休止状態のドキュメントとは対照的です。

于 2009-09-28T12:10:41.380 に答える