【问题标题】:JPA,RELATIONSHIP BEGINEER MANY TO MANY with some complexityJPA,关系初学者多对多,具有一定的复杂性
【发布时间】:2016-02-11 23:25:10
【问题描述】:

我的域模型中有 4 个实体,即教授学院系和角色。 用例是

  1. 教授只能在一所大学工作,这使得一对多 关系(大学 -> 教授)
  2. 教授将在大学阶段担任多个角色(管理员、食品检查员??)
  3. 教授可以为多个部门工作(多对多)
  4. 在每个系教授可能有不同的角色

    class Professor {
        @ManyToOne
        private College workingWithCollege;
        @JoinTable(name = "professor_college_role",
                   joinColumns = @JoinColumn(name = "professor_id"),
                   inverseJoinColumns = @JoinColumn(name = "role_id"))
        @OneToMany
        private Collection<Role> roles;
     }
    
    class College {
    
    }
    
    
    class Department {
    
    }
    
    class DepartMentRole {
        @ManyToOne
        private Department department;
        @ManyToOne
        private Role role;
        //TODO: Dont know how exactly to solve this
    }
    
    class ProfessorDepartmentRole {
         @OneToOne
         private Professor professor;
         @OneToMany
         private Collection DepartmentRole;
    }
    

我们真的需要部门角色吗?如何将教授与部门以及该部门的角色联系起来

【问题讨论】:

  • 大学级别的角色集与部门角色集是否不同?
  • 不一样,但在现实世界中为该角色提供的服务是不同的
  • 那你能不能只创建DepartmentRole类,教授和DepartmentRole之间还有一个多对多的关系?
  • 你认为上面提供的代码足够好还是你会用不同的方式来做??
  • 其他人可能会给出不同的建议,但我必须对其进行测试,而且我现在没有资源去做。试试看,如果您对结果有更多疑问,可以随时返回此帖子。

标签: hibernate jpa many-to-many hibernate-mapping


【解决方案1】:

有很多方法可以实现所涉及的实体及其映射之间的关系。

您定义您的实体:CollegeProfessorDepartmentRole

现在的问题是如何定义在特定Role 中为Department 工作的Professor 之间的关系。一种方法是将这种关系表示为另一个实体——我们称之为ProfessorDepartment

ProfessorDepartment 实体之间的多对多关系仍然可以使用 ProfessorDepartment 作为两者之间的“关系状态”/“关联类”来逻辑表示如 ff 中所示的实体。映射:

  • ProfessorProfessorDepartment 的关系是一对多的
  • ProfessorDepartmentProfessor 的关系是多对一(双向)
  • DepartmentProfessorDepartment 的关系是一对多的
  • ProfessorDepartmentDepartment 的关系是多对一(双向)

现在我们已经将“关系状态”封装到了一个名为 ProfessorDepartment 的实体中,现在我们可以引用 Role 实体了。假设给定的Professor-Department 关系只有一个角色,我们可以将其映射为一对一。

这是一个类图来说明部门、教授和角色之间的关系。

这是数据模型:

这里是每个实体的代码来说明所有的解释:

@Entity
public class College implements Serializable {

    @Id
    @GeneratedValue(strategy=GenerationType.IDENTITY)
    @Column(name="COLLEGE_ID")
    private Long id;

    private String name;

    @OneToMany(mappedBy="college")
    private List<Professor> professorList = new ArrayList<Professor>(); 
...
}

@Entity
public class Professor implements Serializable {

    @Id
    @Column(name="PROF_ID")
    @GeneratedValue(strategy=GenerationType.IDENTITY)
    private Long id;

    private String name;

    @OneToMany(mappedBy="professor")
    private List<ProfessorDepartment> profDepartmentList = new ArrayList<ProfessorDepartment>();

    @ManyToOne
    @JoinColumn(name="COLLEGE_ID")
    private College college;
...
}

@Entity
public class Department implements Serializable {

    @Id
    @Column(name="DEPT_ID")
    @GeneratedValue(strategy=GenerationType.IDENTITY)
    private Long id;

    private String name;

    @OneToMany(mappedBy="department")
    private List<ProfessorDepartment> profDepartmentList = new ArrayList<ProfessorDepartment>();
...
}

@Entity
public class Role implements Serializable {

    @Id
    @GeneratedValue(strategy=GenerationType.IDENTITY)
    @Column(name="ROLE_ID")
    private Long id;

    private String name;
...
}

@Entity
@Table(name="PROFESSOR_DEPARTMENT")
@IdClass(ProfessorDepartmentId.class)
public class ProfessorDepartment implements Serializable {

    @Id
    @ManyToOne
    @JoinColumn(name="DEPT_ID")
    private Department department;

    @Id
    @ManyToOne
    @JoinColumn(name="PROF_ID")
    private Professor professor;

    @OneToOne
    @JoinColumn(name="ROLE_ID")
    private Role role;
...
}

public class ProfessorDepartmentId implements Serializable {

    private Long department;

    private Long professor;
...
}

注意@IdClass注解的使用。 ProfessorDepartment 实体将有一个由ProfessorDepartment 的主键组成的复合主键。

这是一个示例场景:

  1. 我们有教授 John 和 Peter
  2. 他们都在斯坦福大学工作
  3. 我们有3个部门:计算机部、财务部、健康部
  4. John 在财务部担任会计师
  5. Peter 在卫生部门担任医生
  6. John 和 Peter 都在计算机部门工作
  7. John 担任计算机管理员,而 Peter 担任支持专家 - 两者都在计算机部门工作

以下是说明该场景的代码:

    College college = new College();
    college.setName("Stanford University");

    em.persist(college);

    Professor profJohn = new Professor();
    profJohn.setCollege(college);
    profJohn.setName("John");
    college.getProfessorList().add(profJohn);

    em.persist(profJohn);

    Professor profPeter = new Professor();
    profPeter.setCollege(college);
    profPeter.setName("Peter");
    college.getProfessorList().add(profPeter);

    em.persist(profPeter);

    Department compDept = new Department();
    compDept.setName("Computer Department");

    em.persist(compDept);

    Department financeDept = new Department();
    financeDept.setName("Finance Department");

    em.persist(financeDept);

    Department healthDept = new Department();
    healthDept.setName("Health Department");

    em.persist(healthDept);

    Role accountantRole = new Role();
    accountantRole.setName("Accountant");

    em.persist(accountantRole);

    Role doctorRole = new Role();
    doctorRole.setName("Doctor");

    em.persist(doctorRole);

    Role compAdminRole = new Role();
    compAdminRole.setName("Computer Administrator");

    em.persist(compAdminRole);

    Role compSupport = new Role();
    compSupport.setName("Computer Support Specialist");

    em.persist(compSupport);

    // John works as an accountant in Finance Department
    ProfessorDepartment johnInFinanceDept = new ProfessorDepartment();
    johnInFinanceDept.setDepartment(financeDept);
    johnInFinanceDept.setProfessor(profJohn);
    johnInFinanceDept.setRole(accountantRole);
    profJohn.getProfDepartmentList().add(johnInFinanceDept);
    financeDept.getProfDepartmentList().add(johnInFinanceDept);

    em.persist(johnInFinanceDept);

    // Peter works as a doctor in Health Department
    ProfessorDepartment peterInHealthDept = new ProfessorDepartment();
    peterInHealthDept.setDepartment(healthDept);
    peterInHealthDept.setProfessor(profPeter);
    peterInHealthDept.setRole(doctorRole);
    profPeter.getProfDepartmentList().add(peterInHealthDept);
    healthDept.getProfDepartmentList().add(peterInHealthDept);

    em.persist(peterInHealthDept);

    // Both John and Peter works in Computer Department but they are of different roles
    // John works as Computer Administrator
    // Peter works as Computer Support Specialist
    ProfessorDepartment johnInCompDept = new ProfessorDepartment();
    johnInCompDept.setDepartment(compDept);
    johnInCompDept.setProfessor(profJohn);
    johnInCompDept.setRole(compAdminRole);
    profJohn.getProfDepartmentList().add(johnInCompDept);
    compDept.getProfDepartmentList().add(johnInCompDept);

    em.persist(johnInCompDept);

    ProfessorDepartment peterInCompDept = new ProfessorDepartment();
    peterInCompDept.setDepartment(compDept);
    peterInCompDept.setProfessor(profPeter);
    peterInCompDept.setRole(compSupport);
    profPeter.getProfDepartmentList().add(peterInCompDept);
    compDept.getProfDepartmentList().add(peterInCompDept);

    em.persist(peterInCompDept);

完整代码分享在我的Github repo

【讨论】:

  • 实际上还有一个要求,即教授可以在大学担任职务,而他在院系担任的职务完全不同
  • 实际上,您可以采用与为教授-部门关系建模相同的方式对其进行建模——通过关联类。多重性可能会根据您的要求而有所不同。
【解决方案2】:

我会将 ProfessorDepartmentRole 类转换为多对多(如 KLibby 所建议的那样)。因此,为了回答您的问题,我们确实保留了 DepartmentRole 类。此外,您可以从教授类中删除集合角色,因为您可以通过 2 个连接表派生角色。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-08-25
    • 2012-11-25
    • 1970-01-01
    • 2013-02-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多