2016-03-23 26 views
3

我的問題是冬眠以下對象上獲取一個實例時在@OneToMany Set organizationMemberCollection的值獲取休眠檢索空的一對多集合

UserAccount.java

@Entity 
@Table(name="USER_ACCOUNT") 
public class UserAccount { 

    @Id 
    @Column(name = "id", nullable = false) 
    @SequenceGenerator(name = "generator", sequenceName = "USER_ACCOUNT_id_seq", allocationSize=1) 
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "generator") 
    private Long id; 

    @Column(name = "EMAIL", nullable = false) 
    private String email; 

    @Column(name = "PASSWORD_HASH") 
    private String passwordHash; 

    @OneToMany(fetch = FetchType.LAZY, mappedBy = "userAccount") 
    private Set <OrganizationMember> organizationMemberCollection; 

    ... 

    /* 
    * getters and setters 
    */ 
} 

這是「擁有」該關聯的對象:

OrganizationMember.java

@Entity 
@Table(name="ORGANIZATION_MEMBER") 
public class OrganizationMember{ 

    @Id 
    @Column(name = "id", nullable = false) 
    @SequenceGenerator(name = "generator", sequenceName = "ORGANIZATION_MEMBER_id_seq", allocationSize=1) 
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "generator") 
    private Long id; 

    @ManyToOne(fetch = FetchType.LAZY) 
    @JoinColumn(name = "USER_ACCOUNT_ID", nullable = false) 
    private UserAccount userAccount;  

    ... 

    /* 
    * getters and setters 
    */ 
} 

在這個應用中,我們有兩個不同的configuations:

  • 生產,其中休眠連接到PostgreSQL數據庫。 這裏是督促SessionFactory的配置:

    <bean id="sessionFactory" class="org.springframework.orm.hibernate5.LocalSessionFactoryBean"> <property name="hibernateProperties"> <props> <prop key="hibernate.jdbc.batch_size">10</prop> <prop key="hibernate.show_sql">true</prop> <prop key="hibernate.cglib.use_reflection_optimizer">false</prop> </props> </property> ... </bean>

  • 測試,在休眠時conencted到內存中的HSQLDB數據庫:

    <bean id="sessionFactory" class="org.springframework.orm.hibernate5.LocalSessionFactoryBean"> <property name="hibernateProperties"> <props> <prop key="hibernate.dialect">org.hibernate.dialect.HSQLDialect</prop> <prop key="hibernate.show_sql">false</prop> <prop key="hibernate.cglib.use_reflection_optimizer">false</prop> <prop key="hibernate.hbm2ddl.auto">create-drop</prop> <prop key="hibernate.cache.use_second_level_cache">false</prop> <prop key="hibernate.cache.use_query_cache">false</prop> </props> </property> ... </bean>

此問題僅展示進行測試配置;在生產配置一切都很好,我可以得到收藏。 但是,當我在測試配置中獲取UserAccount時,我在organizationMemberCollection屬性(非空集)中獲得null

經過谷歌和Hibernate的doc幾個小時的研究後,我仍然沒有發現任何帖子有關相同的問題/行爲,所以我失去了一些lillte和幫助將不勝感激!

如果需要,我當然可以提供更多信息,謝謝!

編輯:

測試higlighting問題:

@Test 
@Transactional 
public void testFindUserAccount_OrganizationMemberCollectionFetching() { 

    assertNotNull(userAccountDao.findUserAccount("[email protected]")); //NoProblem 
    assertNotNull(userAccountDao.findUserAccount("[email protected]").getCabinetMemberCollection()); //Fails 

} 

用下面findUserAccount

public UserAccount findUserAccount(String email) { 
    if (email == null) { 
     return null; 
    } 
    UserAccount userAccount = (UserAccount) this.sessionFactory 
      .getCurrentSession().createCriteria(UserAccount.class) 
      .add(Restrictions.eq("email", email).ignoreCase()) 
      .uniqueResult(); 
    if (userAccount == null) { 
     throw new ObjectNotFoundException("UserAccount.notFound"); 
    } else { 
     return userAccount; 
    } 
} 
+0

您得到一個空值,因爲您沒有任何與您的userAccount關聯的organizationMemberCollection。你能提供你的測試代碼嗎?也許你忘記在保存OrganizationMember之前忘記調用setUserAccount方法 –

+0

感謝您的快速回答,我認爲在這種情況下,Hibernate會返回我的UserAccount空集,而不是空值,但也許我錯了。 我很確定OrganizationMember具有對用戶帳戶的引用,因爲數據庫在測試之前已被填充。 當我獲取OrganizationMember時,hibernate返回的對象具有對UserAccount的引用。 – Tom

+0

您確定在測試中調用getOrganizationMemberCollection時,持久性上下文不會關閉嗎?如果我們能看到代碼,也許它可以幫助 –

回答

4

的問題是數據庫人口和測試在同一事務中運行,並且休眠緩存這兩個步驟之間沒有被清除。

結果是,hibernate並沒有真正將請求發送到數據庫,而是命中了緩存,並返回了對象而沒有與映射關係進行任何連接。

可能的解決方案是:

  • 填充數據庫在不同的交易。
  • 清理會話後人羣SessionFactory.getCurrentSession().clean();。 (如果需要,請刷新會話:SessionFactory.getCurrentSession().flush();)。

每一種可能性都將迫使一個查詢到真打數據庫,因此連接將出現,並且映射的集合將包含所需的數據(或者是空的,如果加入有沒有結果,但在任何情況下,收藏將不具有null值)。

在我的意見中,第一種解決方案更好,因爲如果測試中出現問題,它不會回滾整個人羣。

0

這是一個延遲加載的集合,所以冬眠沒有做任何事情來初始化它,這很正常,hibernate在這裏返回null ..

我最常做的就是申報的財產空HashSet

@OneToMany(fetch = FetchType.LAZY, mappedBy = "userAccount") 
private Set <OrganizationMember> organizationMemberCollection = new hashSet<>(); 
+0

感謝您的回答,我相信FetchType.LAZY意味着hibernate將使用我的集合上的代理初始化我的集合,而不是空指針。 – Tom

+0

實際上不是......'= new hashSet <>();'告訴hibernate使用代理進行初始化...不是FetchType.LAZY – Pras

+0

嘗試它解決了NPE,但獲得的Set是空的,看起來像hibernate沒有認識到這種映射。 我仍然不明白它爲什麼在一個真正的數據庫上工作,而不是在內存數據庫中。 – Tom