JPA学习 —— 第十课、双向一对多关联关系

双向一对多关联关系

之前讲的都是单向的,而本文讲的是双向的(双向一对多 = 双向多对一)

什么是双向?

我们来对比一下单向和双向
单向多对一:需要在多方创建一方的引用,如:

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

这时就可以在多方关联查询到一方的内容。

单向一对多:需要在一方创建多方的集合引用,如:

@OneToMany
@JoinColumn(name="DEPT_ID")
private List<Employee> employee = new ArrayList<>();

这时就可以在一方关联查询多方的内容。

双向一对多(双向多对一):需要创建双方的引用,即上面两边都要配置。
具体代码略
注意,两个实体类中的@JoinColumn(name=”USER_ID”) 值要一致

插入

Department dept1 = new Department();
dept1.setDeptName("第一个部门");

Employee emp1 = new Employee();
emp1.setEmpName("张三");
emp1.setEmpBirth(new Date());
emp1.setDepartment(dept1);

Employee emp2 = new Employee();
emp2.setEmpName("李四");
emp2.setEmpBirth(new Date());
emp2.setDepartment(dept1);

List<Employee> emps = new ArrayList<>();
emps.add(emp1);
emps.add(emp2);
dept1.setEmployee(emps);
em.persist(dept1);
em.persist(emp1);
em.persist(emp2);

注意:既要把dept放到emp中,也要把emp加到dept中

结果
这里写图片描述

看截图,你会发现有两次的udpate操作,这是因为要维护关联关系。

如果你先插入两个emp,在插入dept,将会发现有四次的update操作,这会影响效率。

要怎么解决呢?

在这种一对多的情况下,我们可以指明由“many”的一方来维护关联关系:在Department实体类中

@OneToMany(mappedBy="department")
private List<Employee> employee = new ArrayList<>();

关于mappedBy:

1) 只有OneToOne,OneToMany,ManyToMany上才有mappedBy属性,ManyToOne不存在该属性;
2) mappedBy标签的name值为本实体在另一方定义的字段名,标记本实体放弃相应的维护权;

比如上面这段代码设置的有mappedBy标签的实体为Department。说明双向关联关系由多方维护,而一方放弃维护权。

注意:使用了mappedBy之后,就不能使用@JoinColumn注解,否则抛异常

再次执行插入操作,发现没有再多出update操作了

这里写图片描述

总结:在一对多和多对一的情况下,插入操作要先插入“一”的对象,再插入“多”的对象,这样可以减少sql语句。如果是双向的,要使用mappedBy指明由“多”的一方(Order)中的user来维护关联关系

查询

Department dept= em.find(Department .class, 1);
System.out.println(dept.getDeptName());
System.out.println(dept.getEmployee().get(0).getEmpName());

这段代码查询没问题,但是如果这样写:

Department dept= em.find(Department .class, 1);
System.out.println(dept);

就会报错

这是因为两个实体类都重写了toString()方法。打印一个对象其实就是调用它的toString()方法。而两边互相调来调去,导致无限死循环下去,因此出现了栈溢出的异常

猜你喜欢

转载自blog.csdn.net/abc997995674/article/details/80229706