hibernación ignora fetch = “unir” en una colección al navegar por el árbol de objetos con el iterador

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

  •  12-09-2019
  •  | 
  •  

Pregunta

tengo un foro con 1..n miembros que tienen cada uno 1..n artículos, por lo que este es mi mapeo:

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

Ahora tengo dos pruebas:

falla éste con 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());
   }

éste tiene éxito

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

La única diferencia es la forma en que cargue el miembro.

La referencia de hibernación dice:

"La estrategia ha podido recuperar la define en el documento de mapeo afecta:

  1. recuperación a través get () o de la carga ()
  2. recuperación que ocurre implícitamente cuando se navega una asociación
  3. Criterios de consultas
  4. consultas HQL si se utiliza ir a buscar subselección "

El ensayo siguiente es el caso 1. (recuperación a través get () o de la carga ()) La prueba no es el caso 2 en mi humilde opinión

¿Por qué "forum.getMembers (). Iterador (). Next ()" no cargar todos los artículos del miembro?

EDIT 1:

Este es mi repositorio:

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

Este es mi 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>

Editar 2: este es mi caso de prueba:

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;

}

}

Realmente no lo entiendo!

¿Fue útil?

Solución 3

Creo que es un error de documentación de hibernación.

En la documentación de referencia que dice:

  

"Por otro lado, puede utilizar unirse   traer, que no es perezoso por naturaleza "

En el libro JPwH que dice, p. 579

  

Por lo tanto, un fetch = "unen" desactiva perezoso   de carga.

No es cierto. Cuando me cambio de artículos de mapeo a

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

prueba de funcionamiento tanto bien, pero la segunda prueba no se ejecuta una unirse al cargar el miembro!

Así que mi conclusión: Eager ir a buscar con la estrategia de combinaciones no afecta initalization de proxy ni desactivar la carga diferida. Esto está en contraste con la documentación de hibernación.

Otros consejos

Los dos casos son realmente muy diferentes.

En el ejemplo en su defecto, que está cargando la entidad Foro, que tiene una colección perezosa inicializado de las entidades miembros. Cuando se trata de navegar a través de la colección, se produce un error porque la colección es un perezoso, y que no se cargó la colección antes de la sesión se cerró.

El ejemplo de trabajo, esto no es "navegación gráfica", que está cargando la entidad miembro directamente, y así no hay semántica perezoso de carga implicados.

La documentación que usted se refiere a formas diferentes involucrados de frasear el primer caso, donde la especificación de carga impaciente en el conjunto de los miembros impediría la falla.

¿Está utilizando HQL en el método findById (...)? Al usar HQL, Hibernate no respetó su FETCH / unirse a los ajustes; es necesario utilizar una cláusula de HQL, como "izquierda unirse a buscar a", para hacer que las asociaciones sean cargados con impaciencia. Además, si usted es 2.x de hibernación, que no será capaz a buscar ansiosamente más de una colección en una sola consulta. Ver la avanzada Problemas frecuentes en el sitio web de hibernación:

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

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top