如何使用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
)
一个人可以拥有许多家庭,而一个家庭可以有许多人居住(即ManyToMany关系)。 此外,住宅可以是一个人的主要住所,但同时也是另一个人的第二住所。
即使数据库架构清晰,我也不确定如何建模这种关系。
我曾想过将映射表person_home拆分为person_primary_home和person_secondary_home,但是如果可能的话我宁愿保留架构。
答案 0 :(得分:1)
这个问题在这里被提出并回答:
How to create a composite primary key which contains a @ManyToOne attribute as an @EmbeddedId in JPA?
您需要四个课程:
您创建的Person.java和Home.java文件与PersonHome.java有一对多的关系。他们将使用@Id字段来识别主键。每个都将定义一个@OneToMany关系,至少有一个mappedBy属性映射到PersonHome实体中它们各自的字段。即在Person.java中你可以有像
这样的东西@OneToMany(cascade = CascadeType.ALL, mappedBy = "Person")
private Collection<PersonHome> personHome;
PersonHome.java将有一个@EmbeddedId字段来标识作为其主键的PersonHomePk实例声明(也就是说,您将使用@EmbeddedId注释表示主键的类的声明而不是@Id列。连接表PersonHome)。任何其他字段都声明为普通列。 PersonHome.java还将向person和home声明两个ManyToOne关系。这些将使用@JoinColumn注释(确保它们具有insertable = false和updatable = 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”声明也需要相同的内容。
为什么你只使用char作为“type”。我推荐一个varchar,所以一旦你离开就维护这个东西的人会在你不在的时候更好地理解代码和数据库。 '分离'更容易理解'd'。
答案 1 :(得分:0)
我相信如果你要在person_home表上除了关系之外还有元数据,你需要使用三个具有两个一对多关系的对象,以便能够访问所有数据。
你可以通过拥有primary_home_id和secondary_home_id来实现从人员表到主表的两个多对一关系来消除这种需求 - 除非我在这里缺少一个要求而且一个人可以拥有多个主要或二手房。