使用 JPA 映射与属性的多对多关系
Posted
技术标签:
【中文标题】使用 JPA 映射与属性的多对多关系【英文标题】:Mapping many-to-many relationship with attributes with JPA 【发布时间】:2017-01-19 01:20:37 【问题描述】:考虑以下实体关系图
[PERSON] (*..N) ------ < is engaged into > ------ (*..N) [ACTIVITY]
/ \
hobby duty
其中[PERSON]
和[ACTIVITY]
是实体,<is engaged into>
是与属性(标志)hobby
和duty
的多对多关系。这些属性是非排他性的:两者都可以是真或假,彼此独立。
如何使用 JPA(或 Hibernate)将此 ERD 映射到如下所示的 Java 对象模型?
@Entity
class Person
Collection<Activity> hobbies; // only activities where hobby=true
Collection<Activity> duties; // only activities where duty=true
@Entity
class Activity
Collection<Person> aficionados; // only people where hobby=true
Collection<Person> professionals; // only people where duty=true
【问题讨论】:
【参考方案1】:非常有趣的案例。
我让它在 JPA 2.1 / Hibernate 5.1 上为我工作。
假设:
个人实体 ID = PERSON_ID 活动实体 ID = ACTIVITY_ID 链接表的名称 = PERSON_ACTIVITY个人实体:
@Entity
class Person
@ManyToMany
@JoinTable(name="PERSON_ACTIVITY",
joinColumns=@JoinColumn(name="PERSON_ID"),
inverseJoinColumns=@JoinColumn(name="ACTIVITY_ID"))
@WhereJoinTable(clause = "hobby = 1")
Set<Activity> hobbyActivities;
@ManyToMany(fetch = FetchType.LAZY)
@JoinTable(name="PERSON_ACTIVITY",
joinColumns=@JoinColumn(name="PERSON_ID"),
inverseJoinColumns=@JoinColumn(name="ACTIVITY_ID"))
@WhereJoinTable(clause = "duty = 1")
Set<Activity> dutyActivities;
活动实体:
@Entity
class Activity
@ManyToMany
@JoinTable(name="PERSON_ACTIVITY",
joinColumns=@JoinColumn(name="ACTIVITY_ID"),
inverseJoinColumns=@JoinColumn(name="PERSON_ID"))
@WhereJoinTable(clause = "hobby = 1")
Set<Person> hobbyPeople;
@ManyToMany(fetch = FetchType.LAZY)
@JoinTable(name="PERSON_ACTIVITY",
joinColumns=@JoinColumn(name="ACTIVITY_ID"),
inverseJoinColumns=@JoinColumn(name="PERSON_ID"))
@WhereJoinTable(clause = "duty = 1")
Set<Person> dutyPeople;
要点:
在所有情况下,集合都必须是一个明确的 Set
每个实体中的一个 @ManyToMany 集必须标记为延迟加载
在进行一些测试时,我发现我必须多次使用 DISTINCT 才能获得重复的结果(但这可能只是我的情况)。
【讨论】:
Map以上是关于使用 JPA 映射与属性的多对多关系的主要内容,如果未能解决你的问题,请参考以下文章
与 Play Framework 1.2.5 JPA 的多对多关系
Fluent NHibernate:如何在关系表上映射具有附加属性的多对多关系?