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

本文介绍了JPA中的双向一对多关联关系,对比了单向与双向的区别,并详细讲解了插入操作中的注意事项,包括如何通过mappedBy指定关联关系的维护方,以此避免多余的更新操作,以及查询时避免无限递归导致的异常。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

双向一对多关联关系

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

什么是双向?

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

@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()方法。而两边互相调来调去,导致无限死循环下去,因此出现了栈溢出的异常

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值