Ruhezustand ignoriert auf einer Sammlung = „join“ holen, wenn das Objekt Baum mit Iterator navigiert

StackOverflow https://stackoverflow.com/questions/1455717

  •  12-09-2019
  •  | 
  •  

Frage

Ich habe ein Forum mit 1..n Mitglieder jeder 1..n Gegenstände mit, so ist dies mein Mapping:

<?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>

Jetzt habe ich zwei Tests:

dies nicht mit 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());
   }

dies gelingt :

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

Der einzige Unterschied ist die Art, wie ich lade Sie das Element.

Die Hibernate Referenz sagt:

"Die Strategie in dem Mapping-Dokument definiert holen beeinflusst:

  1. Abruf über get () oder Last ()
  2. Retrieval, die implizit geschieht, wenn ein Verein navigiert wird
  3. Kriterien Abfragen
  4. HQL-Abfragen, wenn subselect fetching verwendet "

Der nachfolgende Test Fall 1. (Abruf über get () oder Last ()) Der Fehler-Test ist Fall 2 IMHO

Warum "forum.getMembers (). Iterator (). Next ()" nicht alle Artikel des Mitglieds laden?

EDIT 1:

Das ist mein Repository:

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);
    }
}

Das ist mein 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>

Edit 2: dies ist mein Testfall:

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;

}

}

Ich verstehe nicht, es wirklich!

War es hilfreich?

Lösung 3

Ich denke, es ist ein Hibernate-Dokumentation Fehler.

In der Referenzdokumentation heißt es:

  

"Auf der anderen Seite, können Sie beitreten   fetching, die von Natur aus "

Nicht-faul

Im JPwH Buch steht, p. 579

  

Daher ist ein Abruf = „Join“ deaktiviert faul   Laden.

Es ist nicht wahr. Wenn ich auf meine Artikel Mapping ändern

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

beiden Testläufe in Ordnung, aber zweiter Test nicht Join beim Laden des Elements laufen!

So mein Fazit: Eager holen mit Strategie verbindet nicht Proxy initialisiert beeinflussen auch nicht faul Laden deaktivieren. Dies steht im Gegensatz zu der Hibernate-Dokumentation.

Andere Tipps

Die beiden Fälle sind wirklich ganz anders aus.

In dem fehlerhaften Beispiel, ich ist das Forum Einheit geladen, die eine faule initialisierten Sammlung von Mitglied Einheiten hat. Wenn Sie versuchen, durch die Sammlung zu navigieren, schlägt fehl, weil die Sammlung ein fauler ist, und Sie nicht die Sammlung geladen werden, bevor die Sitzung geschlossen wurde.

Das Arbeitsbeispiel, das ist nicht „Graph Navigation“, sind Laden Sie das Mitglied Einheit direkt, und so gibt es keine faul-Laden beteiligt Semantik.

Die Dokumentation, die Sie involviert verschiedene Arten beziehen sind der erste Fall der Phrasierung, wo auf der Menge der Mitglieder das Scheitern verhindern würde eifrig Laden angeben.

Sind Sie mit HQL im findById (...) Methode? Wenn HQL verwenden, wird Hibernate respektieren Ihre nicht Abruf- / Einstellungen verbinden; Sie brauchen eine HQL-Klausel zu verwenden, wie „LEFT JOIN holen“, Assoziationen zu verursachen eifrig geladen werden. Auch, wenn Sie Hibernate 2.x sind, werden Sie nicht in der Lage sein, mit Spannung mehr als eine Sammlung in einer einzigen Abfrage zu holen. Finden Sie im Erweiterten Probleme FAQ auf der Hibernate-Website:

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

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top