-->
These old forums are deprecated now and set to read-only. We are waiting for you on our new forums!
More modern, Discourse-based and with GitHub/Google/Twitter authentication built-in.

All times are UTC - 5 hours [ DST ]



Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 1 post ] 
Author Message
 Post subject: No eager loading of collection with fetch="join"
PostPosted: Fri Oct 09, 2009 4:16 am 
Newbie

Joined: Fri Jun 22, 2007 2:03 pm
Posts: 4
I am using 3.3.1.GA, complete code is attached below.

i have a forum with members which have articles. i want the articles always loaded eagerly when a member is loaded. i defined fetch="join" on the collection mapping.

Code:
   
<class name="Member" table="member">
[..]
      <set name="articles" fetch="join" table="articles"
         inverse="true">
         <key column="member_id" not-null="true" />
         <one-to-many class="Article" />
      </set>
   </class>


So all articles should be loaded whenever a member is loaded.

It does work if i load a member like this:

Code:
Member member = (Member) session.get(Member.class, memberId);


It does not work if i load a member like this:

Code:
Forum forum = (Forum) session.get(Forum.class, forumId);
Iterator<Member> it = forum.getMembers().iterator();
Member member = it.next();


The hibernate reference says:

Quote:
The fetch strategy defined in the mapping document affects:

1. retrieval via get() or load()
2. retrieval that happens implicitly when an association is navigated
3. Criteria queries
4. HQL queries if subselect fetching is used


The succeeding test is case 1. (retrieval via get() or load())
The failing test is case 2 IMHO

Why does "forum.getMembers().iterator().next()" ignore the fetch plan?

I can set lazy="false" to get the articles loaded but they are loaded with a second select. I want the articles to be loaded together with all members when the collection of members is initialized.

I am struggeling with it for years. I posted a similiar question before and on stackoverflow too. Nobody could help me. So i post it again with my complete source code:

here is my complete code:

Code:
package hibernate.fetch;

import java.util.Iterator;

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.cfg.Configuration;

public class PlainTest
{
   private SessionFactory   sessionFactory;
   private Long         forumId;
   private Long         memberId;

   public static void main ( String[] args )
   {
      PlainTest test = new PlainTest();
      test.run();
   }

   public void run ( )
   {
      Configuration cfg = new Configuration().configure();
      sessionFactory = cfg.buildSessionFactory();
      prepare();
      test1();
      test2();
   }

   protected void prepare ( )
   {
      Session session = sessionFactory.openSession();
      Transaction tx = session.beginTransaction();
      System.out.println(">> preparing Test");
      Forum forum = new Forum();
      session.save(forum);
      forumId = forum.getId();

      Member member = new Member();
      forum.addMember(member);
      session.save(member);
      memberId = member.getId();

      Article article = new Article();
      member.addArticle(article);
      session.save(article);

      System.out.println(">> Test prepared");
      tx.commit();
      session.close();
   }

   public void test1 ( )
   {
      Session session = sessionFactory.openSession();
      Transaction tx = session.beginTransaction();
      System.out.println(">> test1");
      Member member = (Member) session.get(Member.class, memberId);
      tx.commit();
      session.close();
      // works fine, articles are eagerly fetched
      System.out.println(member.getArticles().size());
   }

   public void test2 ( )
   {
      System.out.println(">> test2");
      Session session = sessionFactory.openSession();
      Transaction tx = session.beginTransaction();
      Forum forum = (Forum) session.get(Forum.class, forumId);
      Iterator<Member> it = forum.getMembers().iterator();
      Member member = it.next();
      tx.commit();
      session.close();
      // articles were NOT loaded eagerly, throws LazyInitializationException
      System.out.println(member.getArticles().size());
   }

}


Code:
<?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" package="hibernate.fetch">
   <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>



Code:
package hibernate.fetch;

public class Article
{
   private Long   id;
   private String   title   = "test";
   private Member   member;

   public String getTitle ( )
   {
      return title;
   }

   public void setTitle ( String title )
   {
      this.title = title;
   }

   public Long getId ( )
   {
      return id;
   }

   public void setId ( Long id )
   {
      this.id = id;
   }

   public Member getMember ( )
   {
      return member;
   }

   public void setMember ( Member member )
   {
      this.member = member;
   }

}


Code:
package hibernate.fetch;

import java.util.HashSet;
import java.util.Set;

public class Forum
{
   private Long      id;
   private Set<Member>   members   = new HashSet<Member>();
   private String      name   = "test";

   public Set<Member> getMembers ( )
   {
      return members;
   }

   public Long getId ( )
   {
      return id;
   }

   public void setId ( Long id )
   {
      this.id = id;
   }

   public void setMembers ( Set<Member> members )
   {
      this.members = members;
   }

   public String getName ( )
   {
      return name;
   }

   public void setName ( String name )
   {
      this.name = name;
   }

   public void addMember ( Member member )
   {
      members.add(member);
      member.setForum(this);
   }

}

Code:
package hibernate.fetch;

import java.util.HashSet;
import java.util.Set;

public class Member
{
   private Long         id;
   private String         name      = "test";
   private Set<Article>   articles   = new HashSet<Article>();
   private Forum         forum;

   public String getName ( )
   {
      return name;
   }

   public void setName ( String name )
   {
      this.name = name;
   }

   public Set<Article> getArticles ( )
   {
      return articles;
   }

   public void setArticles ( Set<Article> articles )
   {
      this.articles = articles;
   }

   public Long getId ( )
   {
      return id;
   }

   public void setId ( Long id )
   {
      this.id = id;
   }

   public Forum getForum ( )
   {
      return forum;
   }

   public void setForum ( Forum forum )
   {
      this.forum = forum;
   }

   public void addArticle ( Article article )
   {
      articles.add(article);
      article.setMember(this);
   }

}

Code:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-configuration PUBLIC
      "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
      "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
    <session-factory>
        <property name="hibernate.connection.driver_class">org.postgresql.Driver</property>
        <property name="hibernate.connection.url">jdbc:postgresql://localhost:5432/hibernate-fetch</property>
        <property name="hibernate.connection.username">janning</property>
        <property name="hibernate.dialect">org.hibernate.dialect.PostgreSQLDialect</property>
        <mapping resource="Mapping.hbm.xml"/>
    </session-factory>
</hibernate-configuration>


Top
 Profile  
 
Display posts from previous:  Sort by  
Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 1 post ] 

All times are UTC - 5 hours [ DST ]


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum

Search for:
© Copyright 2014, Red Hat Inc. All rights reserved. JBoss and Hibernate are registered trademarks and servicemarks of Red Hat, Inc.