
在许多实际应用场景中,多对多(@manytomany)关系并非没有限制。例如,在一个学生选课系统中,可能存在以下业务规则:
这些限制不能仅仅通过数据库层面的外键约束来表达,而是需要通过应用程序的业务逻辑进行管理。
首先,我们定义Student(学生)和Course(课程)两个实体,它们之间存在多对多关系。
Student 实体:
import com.fasterxml.jackson.annotation.JsonIgnore;
import jakarta.persistence.*;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import java.util.ArrayList;
import java.util.List;
@Entity
@NoArgsConstructor
@Getter
@Setter
public class Student extends BaseEntity { // 假设BaseEntity提供了ID等基础字段
private String name;
private String surname;
@Column(name = "student_number", unique = true)
private String number; // 学号
@JsonIgnore
@ManyToMany(cascade = CascadeType.MERGE, fetch = FetchType.EAGER)
@JoinTable(name = "students_courses",
joinColumns = @JoinColumn(name = "student_id"),
inverseJoinColumns = @JoinColumn(name = "course_id"))
private List<Course> courseList = new ArrayList<>();
// 辅助方法,用于双向关系维护
public void addCourse(Course course) {
if (!this.courseList.contains(course)) {
this.courseList.add(course);
course.getStudentList().add(this);
}
}
public void removeCourse(Course course) {
if (this.courseList.contains(course)) {
this.courseList.remove(course);
course.getStudentList().remove(this);
}
}
}Course 实体:
import com.fasterxml.jackson.annotation.JsonIgnore;
import jakarta.persistence.*;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import java.util.ArrayList;
import java.util.List;
@Entity
@Getter
@Setter
@NoArgsConstructor
public class Course extends BaseEntity { // 假设BaseEntity提供了ID等基础字段
@Column(name = "course_name", unique = true)
private String courseName;
@JsonIgnore
@ManyToMany(mappedBy = "courseList", cascade = CascadeType.ALL, fetch = FetchType.EAGER)
private List<Student> studentList = new ArrayList<>();
// 辅助方法,用于双向关系维护
public void addStudent(Student student) {
if (!this.studentList.contains(student)) {
this.studentList.add(student);
student.getCourseList().add(this);
}
}
public void removeStudent(Student student) {
if (this.studentList.contains(student)) {
this.studentList.remove(student);
student.getCourseList().remove(this);
}
}
}Repository 接口:
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
@Repository
public interface StudentRepository extends JpaRepository<Student, Long> {
}import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
@Repository
public interface CourseRepository extends JpaRepository<Course, Long> {
}JPA配置说明:
数量约束的实现应放在业务逻辑层(Service层),以确保在数据持久化之前进行验证。
自定义业务异常:
为了更好地处理业务规则违规,我们可以定义一个自定义异常。
public class BusinessValidationException extends RuntimeException {
public BusinessValidationException(String message) {
super(message);
}
}StudentService 示例(学生选课):
import jakarta.persistence.EntityNotFoundException;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@Service
public class StudentService {
private final StudentRepository studentRepository;
private final CourseRepository courseRepository;
private static final int MAX_COURSES_PER_STUDENT = 3; // 学生最大选课数
private static final int MAX_STUDENTS_PER_COURSE = 10; // 课程最大容量
public StudentService(StudentRepository studentRepository, CourseRepository courseRepository) {
this.studentRepository = studentRepository;
this.courseRepository = courseRepository;
}
/**
* 学生注册课程
* @param studentId 学生ID
* @param courseId 课程ID
* @return 更新后的学生实体
* @throws以上就是在Spring Boot JPA中实现多对多关系的数量约束的详细内容,更多请关注php中文网其它相关文章!
每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号