2012-06-09 199 views
14

我有兩個類FooBar。在數據庫中的表是這樣的:複合主鍵,外鍵。引用對象或關鍵字?

|Foo| 
|id : INT (PK) | bar_id : INT (PK, FK) | 

|Bar| 
|id : INT (PK) | 

通常我會映射這樣的:

@Entity 
public class Bar 
{ 
    @Id 
    @Column(name = "id") 
    private int id; 

    @OneToMany 
    private Set<Foo> foo; 
} 

@Entity 
public class Foo 
{ 
    @EmbeddedId 
    private FooPK key; 

    @MapsId("barId") 
    @ManyToOne 
    @JoinColumn(name = "bar_id", referencedColumnName = "id") 
    private Bar bar; 
} 

@Embeddable 
public class FooPK 
{ 
    @Column(name = "id") 
    private int id; 
    @Column(name = "bar_id") 
    private int barId; 
} 

然而,ID在FooPK鬆散地映射,需要手動連接。我更喜歡使用Objects來代替鬆散ID的解決方案。 我嘗試以下,但(當然)沒有工作,但我認爲它給了我想達到什麼樣的一個想法:

@Entity 
public class Bar 
{ 
    @Id 
    @Column(name = "id") 
    private int id; 

    @OneToMany 
    private Set<Foo> foo; 
} 

@Entity 
public class Foo 
{ 
    @EmbeddedId 
    private FooPK key; 

    @MapsId("barId") 
    @ManyToOne 
    @JoinColumn(name = "bar_id", referencedColumnName = "id") 
    @Access(AccessType.FIELD) 
    private Bar getBar() 
    { 
     return key.getBar(); 
    } 
} 

@Embeddable 
public class FooPK 
{ 
    @Column(name = "id") 
    private int id; 

    @Transient 
    private Bar bar; 

    //.... 

    @Column(name = "bar_id") 
    @Access(AccessType.PROPERTY) 
    private int getBarId 
    { 
     return bar.getId(); 
    } 
} 

後者解決的另一個問題是,getBarId()方法FooPK需要有一個setBarId(Int)方法。使用ID設置對象可以通過訪問數據訪問層來完成,但是這(在我看來)違反了業務/域/數據層的分離。

那該怎麼辦?使用第一種解決方案並手動同步ID,或者是否有其他(最佳)方法?

回答

23

參考JPA 2: composite primary key classes討論,做出如下更改Foo和FooPK類:

@Entity 
public class Foo { 

    @EmbeddedId 
    private FooPK key; 

    @MapsId("barId") //references EmbeddedId's property 
    @JoinColumn(name = "bar_id", referencedColumnName = "id") 
    @ManyToOne 
    private Bar bar; 
} 

@Embeddable 
public class FooPK { 

    @Column(name = "id") 
    private int id; 
    @Column(name = "bar_id") 
    private int barId; 
} 

我建議首先使它與現場訪問工作,然後將屬性的訪問。

那該怎麼辦?去第一個解決方案,並手動保持ID同步 或有其他(最佳)的做法嗎?

保存自己的痛苦 - 自動生成ID。

+0

這就是第一個例子。我已經看到這是'要走的路',我只是想知道第二個例子是否是一個更清潔的方式。我想這是一個不是嗎? – siebz0r

+0

@ siebz0r哦,對不起,沒有注意到第一個例子是一樣的; o。我認爲,當存在ID而不是映射對象時,更容易查看PK。如果您要通過FooPK進行搜索,則只需要整數,而不需要具有所有不必要屬性的對象。 – JMelnik