在Spring Data JPA和Hibernate中,实现多表关联的操作(包括一对一、一对多、多对一、多对多的查询、删除、关联插入)非常常见。下面将逐步演示这些关系的实现,结合实体映射和JPA的操作来完成。
1. 一对一(One-to-One)
实体映射
假设我们有两个实体:User 和 Address,一个用户只能有一个地址,地址也是唯一属于某个用户。
@Entity
@Table(name = "users")
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String username;
@OneToOne(cascade = CascadeType.ALL) // 级联操作,插入/更新/删除时一起操作
@JoinColumn(name = "address_id", referencedColumnName = "id") // 外键
private Address address;
// getters 和 setters
}
@Entity
@Table(name = "address")
public class Address {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String street;
private String city;
@OneToOne(mappedBy = "address") // 双向一对一关系
private User user;
// getters 和 setters
}
插入、查询、删除
// UserRepository.java
@Repository
public interface UserRepository extends JpaRepository<User, Long> {
}
// 插入
User user = new User();
user.setUsername("John Doe");
Address address = new Address();
address.setStreet("123 Main St");
address.setCity("Springfield");
user.setAddress(address);
userRepository.save(user);
// 查询
User user = userRepository.findById(1L).orElse(null);
if (user != null) {
System.out.println(user.getAddress().getStreet());
}
// 删除
userRepository.deleteById(1L); // 自动级联删除对应的地址
2. 一对多(One-to-Many) & 多对一(Many-to-One)
实体映射
假设一个用户有多个订单,每个订单都属于某一个用户。
@Entity
@Table(name = "users")
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String username;
@OneToMany(mappedBy = "user", cascade = CascadeType.ALL, fetch = FetchType.LAZY) // 一对多关系
private List<Order> orders = new ArrayList<>();
// getters 和 setters
}
@Entity
@Table(name = "orders")
public class Order {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String product;
@ManyToOne(fetch = FetchType.LAZY) // 多对一关系
@JoinColumn(name = "user_id", referencedColumnName = "id") // 外键
private User user;
// getters 和 setters
}
插入、查询、删除
// 插入
User user = new User();
user.setUsername("Jane Doe");
Order order1 = new Order();
order1.setProduct("Product A");
order1.setUser(user);
Order order2 = new Order();
order2.setProduct("Product B");
order2.setUser(user);
user.getOrders().add(order1);
user.getOrders().add(order2);
userRepository.save(user);
// 查询
User user = userRepository.findById(1L).orElse(null);
if (user != null) {
for (Order order : user.getOrders()) {
System.out.println(order.getProduct());
}
}
// 删除
userRepository.deleteById(1L); // 自动级联删除用户的所有订单
3. 多对多(Many-to-Many)
实体映射
假设一个用户可以参加多个课程,一个课程也可以有多个用户参与。
@Entity
@Table(name = "users")
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String username;
@ManyToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY)
@JoinTable(name = "user_course",
joinColumns = @JoinColumn(name = "user_id", referencedColumnName = "id"),
inverseJoinColumns = @JoinColumn(name = "course_id", referencedColumnName = "id")) // 中间表
private Set<Course> courses = new HashSet<>();
// getters 和 setters
}
@Entity
@Table(name = "courses")
public class Course {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
@ManyToMany(mappedBy = "courses", fetch = FetchType.LAZY) // 双向关联
private Set<User> users = new HashSet<>();
// getters 和 setters
}
插入、查询、删除
// 插入
User user = new User();
user.setUsername("John Smith");
Course course1 = new Course();
course1.setName("Math");
Course course2 = new Course();
course2.setName("Science");
user.getCourses().add(course1);
user.getCourses().add(course2);
userRepository.save(user);
// 查询
User user = userRepository.findById(1L).orElse(null);
if (user != null) {
for (Course course : user.getCourses()) {
System.out.println(course.getName());
}
}
// 删除
userRepository.deleteById(1L); // 自动级联删除用户-课程中间表的数据
4. 综合查询
你可以使用 JPQL 或 Native Query 来查询与关联关系相关的数据。例如,查询用户及其订单:
@Query("SELECT u FROM User u JOIN FETCH u.orders WHERE u.id = :userId")
User findUserWithOrders(@Param("userId") Long userId);
5. 总结
通过Spring Data JPA和Hibernate,你可以轻松实现多表关联的操作。常用的关联关系包括:
- 一对一(One-to-One):使用 @OneToOne
- 一对多(One-to-Many):使用 @OneToMany 和 @ManyToOne
- 多对多(Many-to-Many):使用 @ManyToMany 和中间表
这些关系可以通过CascadeType、FetchType控制级联操作和数据抓取方式。同时,通过 JPA Repository 和 JPQL,可以方便地进行查询、插入、更新、删除等操作。


被折叠的 条评论
为什么被折叠?



