2012-06-15 50 views
2

如何使用JPA实现以下关系?如何建立多对多关系

table person (
    id int, 
    name text 
) 

table person_home (
    person_id int, 
    home_id int, 
    type char(1)  -- 'p' = primary, 's' = secondary 
) 

table home (
    id int, 
    address text 
) 

一个人可以有许多家庭,和家庭可以有多少人生活在它(即多对多的关系)。 此外,一个家庭可以成为一个人的主要居所,但同时又是另一个人的二级居所。

即使数据库模式已清除,我也不确定如何建模此关系。

我想过将映射表person_home拆分成person_primary_home和person_secondary_home,但是如果可能的话,我宁愿保留模式。

回答

1

这个问题是相当多问,在这里回答:
How to create a composite primary key which contains a @ManyToOne attribute as an @EmbeddedId in JPA?

您需要四类:

  1. Person.java
  2. Home.java
  3. PersonH​​ome.java
  4. PersonH​​omePk.java

您创建的Person.java和Home.java文件与PersonH​​ome.java具有一对多关系。他们将有@Id字段来识别主键。每个将有一个@OneToMany关系,至少映射到其在PersonH​​ome实体中的各自字段的mappedBy属性。即在Person.java你可以有,而不是一个@Id柱像

@OneToMany(cascade = CascadeType.ALL, mappedBy = "Person") 
private Collection<PersonHome> personHome; 

的PersonH​​ome.java将有一个@EmbeddedId字段来标识PersonH​​omePk实例声明这是其主键(也就是你将有@EmbeddedId注释表示连接表PersonH​​ome的主键的类的声明)。任何其他字段都被声明为普通列。 PersonH​​ome.java还将声明两个ManyToOne关系,分别对应于人和家庭。这些将使用@JoinColumn注释(确保它们具有可插入属性= false和可更新= false)。数据类型将是Person和Home类。即

@EmbeddedId 
protected PersonHomePk personHomePk; 
@Column (name = "type") 
private String type; 
@JoinColumn(name = "person_id", referencedColumnName = "person_id", insertable = false, updatable = false) 
@ManyToOne(optional = false) 
private Person person; 

你也需要同样的“Home”声明。

你为什么只用一个字符作为“类型”。我建议使用varchar,这样一旦你离开后维护这个东西的人会在你不在的时候更好地理解代码和数据库。 '分离'更容易理解'd'。

0

我相信,如果除了person_home表格上的关系之外,您还需要使用三个具有两个一对多关系的对象,以便能够访问所有数据。

通过拥有primary_home_id和secondary_home_id,您可以通过从人员表格到主表格建立两个多对一的关系来消除这种需求 - 除非我在这里缺少一个需求,并且一个人可以有多个小学或中学家庭。

+0

是的,一个人可以有不止一种类型的房屋。所以答案是我需要将映射表建模为一个类? –

+0

如果你想以某种方式获得'type'列,那么我相信是的。 – ametren

+0

我遇到了这个问题,因为这对于关系有元数据非常有用。我相信我找到了一种将其称为“多对多”的方法,但我必须让对象代表这种关系。把它想象成两个“一对多”关系更容易。 – ametren