2010-01-21 98 views
4

假設提供了以下映射:是否可以在沒有對象到對象映射的情況下強制執行外鍵?

<class name="A" table="a_table"> 
    <id name="id"/> 
    <many-to-one name="entityB" column="fk_B" not-null="false" unique="true"/> 
</class> 

<class name="B" table="b_table"> 
    <id name="id"/> 
</class> 

Java類:

public class A { 
    private long id; 
    private B entityB; 
    // getters and setters skipped 
} 

是否有可能改變的Hibernate映射,使外鍵在啓動仍在執行,創建由Hibernate,但是類A看起來將如下所示:

public class A { 
    private long id; 
    private long idOfB; 
    // getters and setters skipped 
} 

據我所知,如果我將<many-to-one...轉換爲<property...這可以工作,但外鍵不會被數據庫強制執行。

我需要這樣做,因爲對象B可能(也可能不會)分別初始化這有時會導致 org.hibernate.LazyInitializationException: could not initialize proxy - no Session異常時a.getB()被稱爲發生。我寧願將它作爲long idOfB,並在需要時加載整個對象;這也會使加載對象A更快。

我相信我的問題是非常相似的this one,但所提供的解決方案(使用延遲加載)是不是在我的情況適合作爲即使我打電話a.getB().getId(),我會得到LazyInitializationException,而如果我叫a.getIdOfB()我不會」噸。

非常感謝。

+0

我強烈建議使用LazyLoading而不是重新發明輪子。你會得到類型安全的實體類,性能完全一樣,並且可能會取消自定義重載代碼。 請注意,如果使用不正確,LazyLoading只會導致LazyLoadingException,即在會話關閉後請求延遲加載。另請注意,請求對象的ID不會導致加載對象。我建議你發佈一個關於LazyLoading具體問題的問題。 – meriton 2010-01-25 18:50:18

+0

相信我,我確實使用LazyLoading。在我無法做到的情況下,這只是一個例子。否則我不會問。 – mindas 2010-01-26 10:26:49

+0

相關問題:[java的 - 休眠 - 外鍵而不是實體](http://stackoverflow.com/questions/6311776/hibernate-foreign-keys-instead-of-entities)。 – 2016-10-14 10:53:27

回答

7

至於說

我明白,如果我轉換<多到一個...成<屬性...這將起作用,但外鍵不會被數據庫強制執行

所以我的建議是:同時使用

public class EntityA { 

    private Integer idOfB; 

    private EntityB entityB; 

    // getter's and setter's 

} 

而且

<class name="A" table="a_table"> 
    <id name="id"/> 
    <property name="idOfB" column="fk_B" not-null="false" unique="true"/> 
    <many-to-one name="entityB" update="false" insert="false" column="fk_B"/> 
</class> 

注意當兩個屬性共享同一列,你必須把設置它在短短的一個物業。否則,Hibernate會抱怨一些錯誤。它解釋了爲什麼我在entityB屬性中定義update =「false」和insert =「false」。

問候,

+0

不錯,漂亮!它的工作原理... – mindas 2010-01-26 17:16:42

+0

我將如何適應傑克遜 – gabber12 2015-07-05 20:30:31

4

你總是可以在Hibernate的hbm.xml文件手動創建外鍵的DDL:

<hibernate-mapping> 
    ... 
    <database-object> 
     <create>[CREATE FK]</create> 
     <drop>[DROP FK]</drop> 
    </database-object> 
</hibernate-mapping> 

你也可以此範圍內,如果不同的方言需要得到支持。

退房5.7. Auxiliary database objects

0

另一個你可以採取的辦法是與你的乙映射,而不是一個映射定義FK。我已經添加了JPA代碼,如果您不使用註釋,則必須將其轉換爲您的hibernate映射文件。

@Entity 
public class B 
{ 
    private long id; 
    private List<A> aList; 

    @Id 
    @Column(name = "ID") 
    public long getId() 
    { 
     return id; 
    } 

    @OneToMany 
    @JoinColumn(name = "B_ID") 
    public List<A> getAList() 
    { 
     return aList; 
    } 
    public void setId(long id) 
    { 
     this.id = id; 
    } 
    public void setAList(List<A> aList) 
    { 
     this.aList = aList; 
    }   
} 

A.java不會是這樣的:

@Entity 
public class A 
{ 
    private long id; 
    private long idOfB; 

    @Id 
    @Column(name = "ID") 
    public long getId() 
    { 
     return id; 
    } 
    @Column(name = "B_ID") 
    public long getIdOfB() 
    { 
     return idOfB; 
    } 
    public void setId(long id) 
    { 
     this.id = id; 
    } 
    public void setIdOfB(long idOfB) 
    { 
     this.idOfB = idOfB; 
    } 
} 
0

我建議你對象對象相關聯得到的Hibernate的全部優勢。我認爲問題是你得到的例外。這是因爲當您嘗試獲取惰性對象時,Hibernate會話已經關閉。在這個博客中有幾個帖子顯示了這個問題的答案,例如這個:link text

如果您使用spring,可以使用OpenEntityManagerInViewFilter,這樣會話將保持打開狀態,直到視圖呈現。

+0

感謝您的回答,但我完全意識到爲什麼延遲加載異常會拋出以及如何處理它們。然而,這是一個特殊情況,我希望框架更加靈活併爲我完成工作。因爲這就是他們寫作的原因,對吧?最後,我不認爲我所要求的對於O-R映射框架來說太多了,不是嗎? – mindas 2010-01-26 10:37:45

相關問題