使用 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] 是实体,&lt;is engaged into&gt; 是与属性(标志)hobbyduty 的多对多关系。这些属性是非排他性的:两者都可以是真或假,彼此独立。

如何使用 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 将一个人分配给一个整数键,但我想要的是一组分配给该键的人。我错过了什么吗? 稍后我会做更多的测试.. 在再次解决您的问题后,我认为我们需要采取不同的策略 我已经发布了新的解决方案。看看吧 测试成功了吗? 该解决方案效果很好,谢谢。我还意识到,在我的情况下,使用 Set 比使用更通用的 Collection 更合适,因为我的连接表中的 FK 构成了该表的 PK,因此我没有任何重复。

以上是关于使用 JPA 映射与属性的多对多关系的主要内容,如果未能解决你的问题,请参考以下文章

与 Play Framework 1.2.5 JPA 的多对多关系

清除与 JPA / JPQL 的多对多关系

Fluent NHibernate:如何在关系表上映射具有附加属性的多对多关系?

JPA中的多对多双向映射

使用 JPA 和 Hibernate 提供程序的多对多关系不会创建主键

JPA 与存储在不同数据库中的用户实体的多对多关系