双向一对多关联关系
前面的博客讲的都是单向的,而本问讲的是双向的(双向一对多 = 双向多对一)
什么是双向?
我们来对比一下单向和双向
单向/双向 | User实体类中是否有List< Order> orders | Order实体类中是否有User user |
---|---|---|
单向多对一 | 无 | 有 |
单向一对多 | 有 | 无 |
双向一对多(双向多对一) | 有 | 有 |
怎么构建关系
User实体类
package com.jpa.helloworld2;import java.util.ArrayList;import java.util.List;import javax.persistence.CascadeType;import javax.persistence.Column;import javax.persistence.Entity;import javax.persistence.FetchType;import javax.persistence.GeneratedValue;import javax.persistence.GenerationType;import javax.persistence.Id;import javax.persistence.JoinColumn;import javax.persistence.OneToMany;import javax.persistence.Table;@Table(name="T_USER")@Entitypublic class User { @Column(name="ID") @GeneratedValue(strategy=GenerationType.AUTO) @Id private Integer id; @Column(name="NAME") private String name; @JoinColumn(name="USER_ID") @OneToMany private List<Order> orders = new ArrayList<>(); public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public List<Order> getOrders() { return orders; } public void setOrders(List<Order> orders) { this.orders = orders; } @Override public String toString() { return "User [id=" + id + ", name=" + name + ", orders=" + orders + "]"; }}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
Order实体类
package com.jpa.helloworld2;import javax.persistence.Column;import javax.persistence.Entity;import javax.persistence.FetchType;import javax.persistence.GeneratedValue;import javax.persistence.GenerationType;import javax.persistence.Id;import javax.persistence.JoinColumn;import javax.persistence.ManyToOne;import javax.persistence.Table;import javax.persistence.TableGenerator;@Table(name="T_ORDER")@Entitypublic class Order { @Column(name="ID") @GeneratedValue @Id private Integer id; @Column(name="ORDER_NAME") private String orderName; @JoinColumn(name="USER_ID") @ManyToOne private User user; public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getOrderName() { return orderName; } public void setOrderName(String orderName) { this.orderName = orderName; } public User getUser() { return user; } public void setUser(User user) { this.user = user; } @Override public String toString() { return "Order [id=" + id + ", orderName=" + orderName + ", user=" + user + "]"; }}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
注意,两个实体类中的@JoinColumn(name=”USER_ID”) 值要一致
插入
Order order1 = new Order();order1.setOrderName("o1");Order order2 = new Order();order2.setOrderName("o2");User user = new User();user.setName("tom");user.getOrders().add(order1);user.getOrders().add(order2);order1.setUser(user);order2.setUser(user);entityManager.persist(user);entityManager.persist(order1);entityManager.persist(order2);
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
注意:既要把user放到order中,也要把order加到user中
结果
看截图,你会发现有两次的udpate操作,这是因为要维护关联关系。
如果你先插入两个order,在插入user,将会发现有四次的update操作,这会影响效率。
要怎么解决呢?
扫描二维码关注公众号,回复:
4858603 查看本文章
在这种一对多的情况下,我们可以指明由“一”的一方来维护关联关系:在User实体类中
@OneToMany(mappedBy="user")private List<Order> orders = new ArrayList<>();
- 1
- 2
注意:使用了mappedBy之后,就不能使用@JoinColumn注解,否则抛异常
再次执行插入操作,发现没有再多出update操作了
总结:在一对多和多对一的情况下,插入操作要先插入“一”的对象,再插入“多”的对象,这样可以减少sql语句。如果是双向的,要使用mappedBy指明由“多”的一方(Order)中的user来维护关联关系
查询
User u = entityManager.find(User.class, 3);System.out.println(u.getName());System.out.println(u.getOrders().get(0).getOrderName());
- 1
- 2
- 3
- 4
这段代码查询没问题,但是如果这样写:
User u = entityManager.find(User.class, 3);System.out.println(u);
- 1
- 2
会出现这样的结果:
这是因为我的User类和Order类都重写了toString()方法。打印一个对象其实就是调用它的toString()方法。而User中有orders,Order中有user,互相调来调去,导致无限死循环下去,因此出现了栈溢出的异常
再分享一下我老师大神的人工智能教程吧。零基础!通俗易懂!风趣幽默!还带黄段子!希望你也加入到我们人工智能的队伍中来!https://blog.csdn.net/jiangjunshow