JPA学习笔记(8)——映射双向一对多关联关系

双向一对多关联关系

前面的博客讲的都是单向的,而本问讲的是双向的(双向一对多 = 双向多对一)

什么是双向?

我们来对照一下单向和双向

单向/双向 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")
@Entity
public 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 + "]";
    }

}

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")
@Entity
public 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 + "]";
    }
}

注意,两个实体类中的@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);

注意:既要把user放到order中。也要把order加到user中

结果
这里写图片描写叙述

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

假设你先插入两个order,在插入user,将会发现有四次的update操作。这会影响效率。

要怎么解决呢?

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

@OneToMany(mappedBy="user")
private List<Order> orders = new ArrayList<>();

注意:使用了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());

这段代码查询没问题,可是假设这样写:

User u = entityManager.find(User.class, 3);
System.out.println(u);

会出现这种结果:
这里写图片描写叙述

这是由于我的User类和Order类都重写了toString()方法。

打印一个对象事实上就是调用它的toString()方法。而User中有orders,Order中有user。互相调来调去。导致无限死循环下去。因此出现了栈溢出的异常

原文地址:https://www.cnblogs.com/zsychanpin/p/7295529.html