背景
Spring Data JPA 提供了几种装饰器用来指定表的关系,分别是
@OneToOne、@OneToMany、@ManyToOne、@ManyToMany、@JoinColumn、@JoinTable
OneToOne
假设 User 跟 Address 是一对一关系.
单向
通过 User 可以找到 Adress, 通过 Adress 无法找到 User.
这种情况只配置 User 表.
@Entity
@Table(name = "user")
@Getter
@Setter
@AllArgsConstructor
@NoArgsConstructor
@Builder
public class User {
// 设置级联删除, 删User 也删 Address
@OneToOne(cascade = CascadeType.ALL)
@JoinColumn(name = "address_id", nullable = false)
private Address address;
}
双向
通过 User 可以找到 Adress, 通过 Adress 也可以找到 User.
这种情况配置两张表.
@Entity
@Table(name = "user")
@Getter
@Setter
@AllArgsConstructor
@NoArgsConstructor
@Builder
public class User {
// 设置级联删除 CascadeType.ALL , 删 User 也删 Address
@OneToOne(cascade = CascadeType.ALL)
@JoinColumn(name = "address_id", nullable = false)
private Address address;
}
@Entity
@Table(name = "address")
@Getter
@Setter
@AllArgsConstructor
@NoArgsConstructor
@Builder
public class Address {
// 在被关联的表添加 mappedBy 可以指定双向结构
// 原理 通过User类中的 address 属性 再找到 joinColumn 再找到User
// 设置级联删除 CascadeType.ALL, 删 Address 也删 User
// @OneToOne(mappedBy = "address", cascade = CascadeType.ALL)
// 删 address 不删 user 去掉 CascadeType.DETACH
@OneToOne(mappedBy = "address", cascade = {CascadeType.DETACH,CascadeType.MERGE,CascadeType.PERSIST,CascadeType.REFRESH})
private User user;
}
OneToMany
假设 Reservation 和 Comment 是单向一对多的关系.
通过 Reservation 可以找到所有的 Comment, 通过 Comment 无法找到 Reservation .
单向
@Entity
@Table(name = "reservation")
@Getter
@Setter
@AllArgsConstructor
@NoArgsConstructor
@Builder
public class Reservation {
// 单向 OneToMany 在 One 的一方 添加 @JoinColumn 属性指定外键, 该外键在多方添加
@OneToMany(cascade = CascadeType.ALL)
@JoinColumn(name = "reservation_id", nullable = false)
private List<Comment> comments;
}
双向
假设 User 和 Reservation 是双向一对多的关系.
通过 User 可以找到所有的 Reservation, 通过每个 Reservation 也可以找到 User.
@Entity
@Table(name = "user")
@Getter
@Setter
@AllArgsConstructor
@NoArgsConstructor
@Builder
public class User {
// 在 One 方添加 mappedBy
// 原理 通过找到 Reservation 中的 user 属性找到 Reservation
// 去掉 CascadeType.DETACH 删 user 不删订单
// 某些情况下可也可以删订单 CascadeType.ALL
@OneToMany(mappedBy = "user", cascade = {CascadeType.DETACH,CascadeType.MERGE,CascadeType.PERSIST,CascadeType.REFRESH})
private List<Reservation> reservations;
}
@Entity
@Table(name = "reservation")
@Getter
@Setter
@AllArgsConstructor
@NoArgsConstructor
@Builder
public class Reservation {
// 在 many 的一侧 添加 @JoinColumn 指定外键的名称
@ManyToOne
@JoinColumn(name = "user_id", nullable = false)
private User user;
}
ManyToMany
User 和 Teacher 是多对多的关系.
@Entity
@Table(name = "user")
@Getter
@Setter
@AllArgsConstructor
@NoArgsConstructor
@Builder
public class User {
// 指定中间表名 user_teacher 还有 user_id 和 teacher_id 外键
// 去掉 cascade 中的级联删除
@ManyToMany(cascade = {CascadeType.DETACH,CascadeType.MERGE,CascadeType.PERSIST,CascadeType.REFRESH})
@JoinTable(name = "user_teacher",
joinColumns = @JoinColumn(name = "user_id", nullable = false),
inverseJoinColumns = @JoinColumn(name = "teacher_id", nullable = false)
)
private List<Teacher> teachers;
}
@Entity
@Table(name = "teacher")
@Getter
@Setter
@AllArgsConstructor
@NoArgsConstructor
@Builder
public class Teacher {
// 另一方需要加 mappedBy 属性
@ManyToMany(mappedBy="teachers")
private List<User> users;
}