使用JPA映射与属性的多对多关系

时间:2017-01-19 01:20:38

标签: java hibernate jpa orm hibernate-mapping

考虑以下实体关系图

[PERSON] (*..N) ------ < is engaged into > ------ (*..N) [ACTIVITY]
                          /          \
                       hobby        duty

其中[PERSON][ACTIVITY]是实体,而<is engaged into>是与属性(标志)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 个答案:

答案 0 :(得分:1)

非常有趣的案例。

我在JPA 2.1 / Hibernate 5.1上为我工作。

假设:

  • Person实体的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;
}

关键点

  • 在所有情况下,集合必须明确为集合

  • 每个实体中的一个@ManyToMany集必须标记为延迟加载

  • 在进行一些测试时,我发现我必须多次使用DISTINCT才能获得重复的结果(但这可能只是我的情况)。