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>