跳到主要内容

多表关联

一对一(单向)

  • 通过@OneToOne设置。
    • fetch设置是否懒加载。(fetch = FetchType.LAZY
    • cascade设置关联操作。例如设置成cascade = CascadeType.PERSIST时,关联的对象不需要自己调用持久化方法,会自动持久化。
    • orphanRemoval关联删除。通常在修改的时候使用。一旦把关联的数据设置成null,或者修改为其他的数据,旧的数据会被删除。默认为false
    • optional设置关联的对象是否可以为空。默认为true。用来限制关联的对象不能为null
  • 外键名称通过@JoinColumn设置。

一对一(双向)

  • 基本使用方法参照一对一单向。
  • 设置双向关联不能在两个表里都设置外键(@JoinColumn),因为两个表互相有外建约束会造成两个表里的数据都无法删除。
    • 要在其中一个表里放弃外键约束,把Id设置成不受另一个表约束的数值,或者把外键删除。
  • 放弃外键约束可以用@OneToOne(mappedBy = "..."),将外键约束交给另一方维护。

一对多/多对一

// 多对一的时候定义的是在本表指向另一方主键的外键名。
@ManyToOne
@JoinColumn(name="ADDR_ID")
public Address getAddress() { return address; }

// 比如顾客有很多订单,要在顾客这一方维护单向一对多,定义的是在订单表的外键。
@OneToMany
@JoinColumn(name="CUST_ID") // join column is in table for Order
public Set<Order> getOrders() {return orders;}
  • 一对多默认是懒加载。

单向和双向有什么区别?

这篇文章有详细的解释。 https://www.baeldung.com/jpa-joincolumn-vs-mappedby

  • 无论单向还是多向,它对数据库的映射是没有影响的。它仅仅是定义了领域模型(domain model)里的关系。
  • 对于双向关系,我们一般定义所有方(owning side)与参照方(inverse or referencing side)。
  • @JoinColumn定义的是所有方,而mappedBy属性定义了参照方。
  • 在一对多或者多对一的关系中,所有方一般定义在多的一方,就是说many的那一方一般拥有外键的定义。比如说一个员工可以有很多个电子邮件,@JoinColumn就定义在电子邮件这一方,它有一个叫做employee_id的外键指向Employee的主键。需要注意mappedBy的值应为所有方里定义的属性名。
@Entity
public class Email {

@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;

@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "employee_id")
private Employee employee;

// ...

}

@Entity
public class Employee {

@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;

@OneToMany(fetch = FetchType.LAZY, mappedBy = "employee")
private List<Email> emails;

// ...
}