2012-06-09 202 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