JPA对象关系-双向多对多
JPA对象关系-双向多对多
关系型数据库设计时,多对多关系一般会创建1个中间表维护关系,类似JPA 一对多时,默认生成1个中间表维护关系。
单向多对多和单向一对多其实是一样的,都会生成1个中间表维护关系。不在详细说明,这里主要说一下双向多对多
下面部门和员工为例,1个部门可以有多个员工,同理1个员工可以在多个部门任职。
1、类型定义
@Data
@Entity
public class Department {
@Id
@GeneratedValue
private long id;
private String name;
@ManyToMany
public List<Employee> employees;
}
@Data
@Entity
public class Employee {
@Id
@GeneratedValue
private long id;
private String name;
@ManyToMany
private List<Department> departments;
}
2、测试保存
@Test
public void save(){
Department d1=new Department();
d1.setName("财务部");
Department d2=new Department();
d2.setName("人事部");
Employee gg=new Employee();
gg.setName("gg");
Employee jl=new Employee();
jl.setName("jl");
//设置关系
List<Employee> employees=new ArrayList<>();
employees.add(gg);
employees.add(jl);
d1.setEmployees(employees);
d2.setEmployees(employees);
List<Department> departments=new ArrayList<>();
departments.add(d1);
departments.add(d2);
gg.setDepartments(departments);
jl.setDepartments(departments);
//保存
EntityManager entityManager = JpaUtil.getEntityManager();
entityManager.getTransaction().begin();
entityManager.persist(d1);
entityManager.persist(d2);
entityManager.persist(gg);
entityManager.persist(jl);
entityManager.getTransaction().commit();
entityManager.close();
}
3、控制台SQL打印输出
发现打印的SQL,在保存部门和员工后,保存关系时,向2个关系表都插入了数据。JPA默认每个对象上的@ManyToMany
都会生成一个关系表,各自维护各自的关系表。此时我们需要让1方放弃关系维护。
Hibernate: insert into Department (name) values (?)
Hibernate: insert into Department (name) values (?)
Hibernate: insert into Employee (name) values (?)
Hibernate: insert into Employee (name) values (?)
Hibernate: insert into Department_Employee (Department_id, employees_id) values (?, ?)
Hibernate: insert into Department_Employee (Department_id, employees_id) values (?, ?)
Hibernate: insert into Department_Employee (Department_id, employees_id) values (?, ?)
Hibernate: insert into Department_Employee (Department_id, employees_id) values (?, ?)
Hibernate: insert into Employee_Department (Employee_id, departments_id) values (?, ?)
Hibernate: insert into Employee_Department (Employee_id, departments_id) values (?, ?)
Hibernate: insert into Employee_Department (Employee_id, departments_id) values (?, ?)
Hibernate: insert into Employee_Department (Employee_id, departments_id) values (?, ?)
4、解决双向多对多2个关系表问题 mappedBy
随便让1方放弃关系维护,这里让员工对象mappedBy
放弃关系维护,如下代码。
@Data
@Entity
public class Employee {
@Id
@GeneratedValue
private long id;
private String name;
//放弃关系维护
@ManyToMany(mappedBy = "employees")
private List<Department> departments;
}
@Data
@Entity
public class Department {
@Id
@GeneratedValue
private long id;
private String name;
@ManyToMany
public List<Employee> employees;
}
双向多对多关系时,如何手动维护关系 @JoinTable
直接@ManyToMany
JPA 默认会生成一个关系表,维护关系,但是大部分情况下,中间关系表都是手动创建的,如何不让JPA默认生成关系表呢?用@JoinTable
指定关系表,关系表每个列与外键表的哪个列进行对应。另外一方同样放弃关系维护即可。
@Data
@Entity
public class Department {
@Id
@GeneratedValue
private long id;
private String name;
//@JoinTable 多对多关系,name 指定中间表名称
//joinColumns 指定当前对象哪个列referencedColumnName,和中间表哪个列name对应
//inverseJoinColumns 指定依赖对象,哪个列referencedColumnName,和中间表哪个列name对应
@ManyToMany
@JoinTable(name = "Department_Employee",
joinColumns = @JoinColumn(name = "departments_id",referencedColumnName = "id")
,inverseJoinColumns = @JoinColumn(name = "employees_id",referencedColumnName = "id"))
public List<Employee> employees;
}
@Data
@Entity
public class Employee {
@Id
@GeneratedValue
private long id;
private String name;
//放弃关系维护
@ManyToMany(mappedBy = "employees")
private List<Department> departments;
}