future.png
珠玑随笔

联系:

future.png

版权 © 2022 by Hsu

技术: Gatsby

样式: Bulma

许可: CC BY NC SA 4.0

Spring Data JPA 表关系

2022年01月09日

Hsu

1分钟

背景

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;
}

参考

http://www.codebaoku.com/it-java/it-java-231172.html