2011-09-22 34 views
7

我的問題是關於JPA 2.0與Hibernate,@OneToOne關係和延遲加載。JPA 2.0/Hibernate:爲什麼用「@OneToOne」獲取LAZY可以開箱即用?

首先我的設置:

  • 春3.0.5.RELEASE
  • SprnigData JPA 1.0.1.RELEASE
  • 的Hibernate 3.5.2決賽
  • DBMS:在PostgreSQL 9.0

我最近遇到這樣一個事實,即@OneToOne關係不能以懶惰的方式獲取(FetchType.LAZY),至少不是沒有字節碼的工具n,編譯時間編織等。許多網站在那裏說這一點,例如:

的事情是,我的設置中,@OneToOne實體的延遲加載似乎工作「開箱即用」,我真的很想理解爲什麼。請看看我的單元測試:

@Test 
@Transactional 
public void testAvatarImageLazyFetching() 
{ 
    User user = new User(); 
    user.setAvatarImage(new AvatarImage()); 

    User = userRepository.save(user); 

    entityManager.flush(); 
    entityManager.clear(); 

    User loadedUser = userRepository.findOne(user.getId()); 
    assertNotNull(loadedUser); 

    PersistenceUtil persistenceUtil = Persistence.getPersistenceUtil(); 

    assertTrue(persistenceUtil.isLoaded(loadedUser)); 
    assertFalse(persistenceUtil.isLoaded(loadedUser, "avatarImage")); 
} 

這個測試用例是成功的,並在Hibernate的SQL日誌輸出,我可以清楚地看到,該「avatarImage」會不會牽強,只是「用戶」 (只是一個單一的SELECT,JOIN沒有,到 「AvatarImage」 表等無法訪問)

User類單向@OneToOne relationshop看起來是這樣的:

@OneToOne(cascade = CascadeType.ALL, fetch = FetchType.LAZY) 
private AvatarImage avatarImage; 

所以,一切都非常簡單 - 它似乎工作。

重複我的問題:爲什麼它工作,爲什麼可以懶惰地提取「AvatarImage」,雖然它是由@OneToOne關聯引用的?

我真的很感謝你可以提供的任何幫助

非常感謝!

回答

8

延遲加載OneToOne關係的問題僅在其反向部分(標記爲mappedBy屬性的部分)上。它在關係的擁有方面運作良好。 T 他在數據庫級別上的區別很明顯。在你的情況下,問題是如果用戶數據庫表中包含一個AvatarImage id作爲其中一列或其他方式。 如果用戶表有一個id爲AvatarImage的列,那麼延遲加載將按照你所說的「開箱即用」工作,但它不會以相反的方式工作。

3

當某種形式的字節碼檢測被執行時,惰性抓取可以在@OneToOne帶註釋的關係中與Hibernate JPA提供者一起使用。在你的情況下,我們可以排除構建時間檢測(從你的評論中推斷出它可以直接使用)。這給你帶來了運行時編織的可能性,這在休眠& Spring中是很有可能的。在最近發佈的Hibernate中,Javassist被用作Hibernate的運行時字節碼工具框架,與CGLIB的另一種替代方案(which has been deprecated since Hibernate 3.5.5)相反。

Javassist是否在Spring中啓用的問題很容易回答。 Hibernate EntityManager(它是委派給Hibernate Core的JPA 2.0提供者)需要Javassist,因此它應該位於Hibernate的類路徑中,從而允許運行時編織這些類。您可以通過設置斷點(在連接到應用程序服務器的遠程調試器中)來確認這一點,並且您會注意到User類的Hibernate管理實例將不包含對AvatarImage實例的引用;相反,它會包含對名稱類似於<package_name>.AvatarImage_$$_javassist_0(這是允許延遲獲取的代理)的增強類的引用。

相關問題