我有一个论坛,有 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>
现在我有两个测试:
这个失败并出现 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());
}
唯一的区别是我加载成员的方式。
休眠参考说:
“映射文档中定义的获取策略影响:
- 通过 get() 或 load() 检索
- 导航关联时隐式发生的检索
- 条件查询
- 如果使用子选择提取,则 HQL 查询"
成功的测试是案例 1。(通过 get() 或 load() 检索)失败的测试是案例 2 恕我直言
为什么“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;
}
}
我真的不明白!