2009-09-21 68 views
2

导航对象树时,我有1..1成员各有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()); 
    } 

这一个成功

唯一的区别是我加载成员的方式。

Hibernate参考表示:

“的映射文档中定义的抓取策略影响:

  1. 通过get检索()或负载()
  2. 检索这种情况发生隐式时的关联是导航
  3. 条件查询
  4. HQL查询是否使用子查询获取“

的后续测试是壳体1(通过get检索()或负载()) 失败测试是壳体2 IMHO

为什么“forum.getMembers()。下一个迭代()()。 “不加载所有成员的文章?

编辑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; 

} 

}

我真的不明白!

回答

-1

我认为这是一个Hibernate文档错误。

在参考文档,它说:

“在另一方面,你可以使用加入 取,这是不可懒惰成性”

在JPwH本书,它说,p。 579

因此,取= “加入” 禁用延迟 加载。

这是不正确的。当我更改我的文章映射到

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

这两个测试运行良好,但第二次测试不加载成员时运行加入!

所以我的结论是:用连接策略的渴望提取不会影响代理初始化,也不会影响延迟加载。这与hibernate文档相反。

+0

这并不那么简单,取/连接行为取决于你如何询问对象,例如你是否使用HQL,Criteria API,session.get()等 – skaffman 2009-09-28 12:13:18

+0

休眠文档说,延迟加载与加入连接,所以它应该影响对象也加载 但如果你明白它..你能解释为什么grapgh没有加载?我没有使用HQL或Criteria Api,只是session.get()和导航对象树。 – Janning 2009-09-29 10:09:44

1

这两种情况真的很不一样。

在失败的示例中,您正在加载Forum实体,该实体具有延迟初始化的成员实体集合。当您尝试浏览集合时,它会失败,因为集合是懒惰集合,并且在会话关闭之前未加载集合。

工作示例中,这不是“图导航”,您直接加载成员实体,因此没有涉及延迟加载语义。

您提到的文档涉及第一种情况的不同表述方式,其中指定在成员集上进行预先加载可以防止失败。

+0

实际上,在这种情况下,我不认为这是真的。他在调用'endTransaction()'之前获得“成员”,因此推测它仍然处于会话中。后续的'member.getArticles()。size()'调用失败。更令人困惑的问题是第二次测试成功的原因。看到'fetch ='join''不应该重写默认'lazy =“true”'设置它看起来应该失败了。我猜测它是先前加载并初始化从会话中获得的“成员”。 – ChssPly76 2009-09-21 18:54:33

0

您是否在findById(...)方法中使用HQL?在使用HQL时,Hibernate不尊重你的读取/加入设置;您需要使用HQL子句(如“左连接提取”)来引起关联加载。此外,如果您是Hibernate 2.x,您将无法在单个查询中热切地获取多个集合。参考Hibernate网站上的高级问题FAQ:

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

+0

请看看我的**编辑1 **:我不使用HQL,而是使用spring hibernateTemplate的标准会话方法。我知道HQL – Janning 2009-09-23 15:54:49

+0

的“限制”好吧,对不起,没有多大的帮助=( – RMorrisey 2009-09-23 16:00:21