【问题标题】:Mapping many-to-many relationship with attributes with JPA使用 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
}

【问题讨论】:

    标签: java hibernate jpa orm hibernate-mapping


    【解决方案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,因此我没有任何重复。
    猜你喜欢
    • 2016-03-04
    • 1970-01-01
    • 1970-01-01
    • 2013-05-19
    • 1970-01-01
    • 1970-01-01
    • 2021-12-19
    • 1970-01-01
    • 2014-08-17
    相关资源
    最近更新 更多