JPA,关系初学者多对多,有一定的复杂性
JPA,RELATIONSHIP BEGINEER MANY TO MANY with some complexity
我的领域模型中有 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;
}
我们真的需要部门角色吗?如何将教授与部门联系起来以及该部门的角色
我会将 ProfessorDepartmentRole class 转换为多对多(如 KLibby 所建议)。因此,为了回答您的问题,我们确实保留了 DepartmentRole class。此外,您还可以从 Professor class 中删除集合角色,因为您可以通过 2 个连接表派生角色。
实现所涉及的实体及其映射之间的关系的方法有很多种。
您定义实体:College
、Professor
、Department
和 Role
现在的问题是如何定义 Professor
在特定 Role
中为 Department
工作之间的关系。一种方法是将这种关系表示为另一个实体——我们称之为 ProfessorDepartment
。
Professor
和 Department
实体之间的多对多关系仍然可以使用 ProfessorDepartment
作为 "relationship state"/ "association class" 在 2 个实体之间,如 ff 中所示。映射:
- 从
Professor
到ProfessorDepartment
的关系是一对多
- 从
ProfessorDepartment
到 Professor
的关系是多对一(双向)
- 从
Department
到ProfessorDepartment
的关系是一对多
- 从
ProfessorDepartment
到 Department
的关系是多对一(双向)
现在我们已经将 "relationship state" 封装到一个名为 ProfessorDepartment 的实体中,我们现在可以引用 Role 实体。假设对于给定的 Professor
-Department
关系只有一个角色,我们可以将其映射为一对一。
这里有一个 class 图表来说明部门、教授和角色之间的关系。
这是数据模型:
以下是每个实体的代码来说明所有的解释:
@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
实体将有一个由 Professor
和 Department
的主键组成的复合主键。
这是一个示例场景:
- 我们有教授,约翰和彼得
- 他们都在斯坦福大学工作
- 我们有3个部门:计算机部、财务部、卫生部
- John 在财务部担任会计
- Peter 在卫生部当医生
- John 和 Peter 都在计算机部门工作
- 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.
我的领域模型中有 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; }
我们真的需要部门角色吗?如何将教授与部门联系起来以及该部门的角色
我会将 ProfessorDepartmentRole class 转换为多对多(如 KLibby 所建议)。因此,为了回答您的问题,我们确实保留了 DepartmentRole class。此外,您还可以从 Professor class 中删除集合角色,因为您可以通过 2 个连接表派生角色。
实现所涉及的实体及其映射之间的关系的方法有很多种。
您定义实体:College
、Professor
、Department
和 Role
现在的问题是如何定义 Professor
在特定 Role
中为 Department
工作之间的关系。一种方法是将这种关系表示为另一个实体——我们称之为 ProfessorDepartment
。
Professor
和 Department
实体之间的多对多关系仍然可以使用 ProfessorDepartment
作为 "relationship state"/ "association class" 在 2 个实体之间,如 ff 中所示。映射:
- 从
Professor
到ProfessorDepartment
的关系是一对多 - 从
ProfessorDepartment
到Professor
的关系是多对一(双向) - 从
Department
到ProfessorDepartment
的关系是一对多 - 从
ProfessorDepartment
到Department
的关系是多对一(双向)
现在我们已经将 "relationship state" 封装到一个名为 ProfessorDepartment 的实体中,我们现在可以引用 Role 实体。假设对于给定的 Professor
-Department
关系只有一个角色,我们可以将其映射为一对一。
这里有一个 class 图表来说明部门、教授和角色之间的关系。
这是数据模型:
以下是每个实体的代码来说明所有的解释:
@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
实体将有一个由 Professor
和 Department
的主键组成的复合主键。
这是一个示例场景:
- 我们有教授,约翰和彼得
- 他们都在斯坦福大学工作
- 我们有3个部门:计算机部、财务部、卫生部
- John 在财务部担任会计
- Peter 在卫生部当医生
- John 和 Peter 都在计算机部门工作
- 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.