2009-09-21 72 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