2013-08-01 106 views
42

我遇到了這樣的問題:一對一延遲加載在hibernate中不起作用。我已經解決了它,但仍不正確瞭解會發生什麼。休眠:一對一延遲加載,可選= false

我的代碼(延遲加載這裏行不通,當我拉人 - 地址也獲取):

@Entity 
public class Person{ 

    @Id 
    @SequenceGenerator(name = "person_sequence", sequenceName = "sq_person") 
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "person_sequence") 
    @Column(name = "id") 
    private long personID; 

    @OneToOne(mappedBy="person", cascade=CascadeType.ALL, fetch = FetchType.LAZY) 
    private Adress address; 
    //.. getters, setters 
} 

@Entity 
public class Address { 

    @Id 
    @Column(name="id", unique=true, nullable=false) 
    @GeneratedValue(generator="gen") 
    @GenericGenerator(name="gen", strategy="foreign", [email protected](name="property", value="person")) 
    private long personID; 

    @PrimaryKeyJoinColumn 
    @OneToOne 
    private FileInfo person; 
} 

:如果我在OneToOne關係添加optional=false,懶惰loading 正常工作

@OneToOne(mappedBy="person", cascade=CascadeType.ALL, optional = false, fetch = FetchType.LAZY) 
private Adress address; 

問題/懇求:請向我解釋optional=false註釋如何幫助實現延遲加載。

P.S.我讀過的帖子post1post2,並瞭解爲何僅是簡單OneToOne不能偷懶,但我還不能掌握optional=false魔術。

+0

嘿@Volodymyr,我和你有同樣的問題。我試圖從實體中分離出一個BLOB列。父實體具有子實體。子實體包含二進制列。父母和孩子是'相同的表',所以我使用@OneToOne關係。雖然我使用LAZY fetchType,但它似乎不起作用。當我把'可選=假',它的作品。任何解釋將真正讚賞。 – Emerald214

+0

@ Emerald214對不起,那是2年前。目前我正在寫JS Mobile,並且不能幫助您 –

+0

OneToOne可選= false與CascadeType.PERSIST無效 請參閱: https://hibernate.atlassian.net/browse/HHH-9670 – sliver

回答

62

如果協會是可選的,Hibernate有沒有辦法知道,如果一個地址存在一個特定的人,而不會發出查詢。所以它不能用代理填充地址字段,因爲可能沒有地址引用該人員,並且不能用空值填充它,因爲可能有地址引用該人員。

當你做出associatio強制性的(即optional=false),它信任你,並假定一個地址存在,因爲該協會是強制性的。所以它直接用代理填充地址字段,知道有一個地址引用這個人。

+0

可選= false如果嘗試在沒有Adresse的情況下保存Personne,則不起作用:「org.hibernate.PropertyValueException:not-null屬性引用null或瞬態值:」 –

+3

optional = false表示...該地址不是可選的。所以這是強制性的。因此將其設置爲null會引發異常。這是相當期望的。 –

+0

因此,OneToOne,延遲加載,使用共享的主鍵和可選的一方,是休眠不可能的,對吧? –

5

最簡單的一種是假的一個一對多的關係。這將起作用,因爲延遲加載收集比單一可空屬性的延遲加載容易得多,但通常如果使用複雜的JPQL/HQL查詢,此解決方案非常不方便。

另一種是使用編譯時字節碼裝置。有關更多詳細信息,請閱讀Hibernate文檔:19.1.7。使用lazy屬性獲取。請記住,在這種情況下,您必須將@LazyToOne(LazyToOneOption.NO_PROXY)註釋添加爲一對一關係才能使其變爲惰性。將提取設置爲LAZY是不夠的。

最後一個解決方案是使用運行時字節碼工具,但它只適用於那些在成熟的JEE環境中將Hibernate用作JPA提供程序的人(在這種情況下,將「hibernate.ejb.use_class_enhancer」設置爲true應該這樣做:實體管理器配置)或者使用Hibernate和Spring配置來執行運行時編織(這可能很難在一些較早的應用程序服務器上實現)。在這種情況下,@LazyToOne(LazyToOneOption.NO_PROXY)註釋也是必需的。