Spring Boot中jakarta.persistence.Check约束失效及导入报错问题
问题解决:演员关联电影时无法删除的约束实现及依赖冲突修复
你遇到的核心问题有两个:一是依赖版本冲突导致jakarta.persistence.Check无法被编译器识别,二是错误地在中间关联表上添加约束(你的需求是限制Actor的删除操作,而非中间表)。以下是具体解决步骤:
一、修复Gradle依赖冲突
Spring Boot 3.0.x基于Jakarta EE 9规范,必须使用适配Jakarta的依赖。你的gradle配置同时混入了旧版Java EE的javax.persistence-api和仅支持Java EE的Hibernate 5.x,导致类路径混乱。修改后的build.gradle如下:
plugins { id 'java' id 'org.springframework.boot' version '3.0.5' id 'io.spring.dependency-management' version '1.1.0' id 'io.freefair.lombok' version '8.0.1' } group = 'com.bill' version = '0.0.1-SNAPSHOT' sourceCompatibility = '17' configurations { compileOnly { extendsFrom annotationProcessor } } repositories { mavenCentral() } dependencies { // 依赖Spring Boot Starter自动管理版本,无需手动指定JPA、Hibernate等组件版本 implementation 'org.springframework.boot:spring-boot-starter-web' implementation 'org.springframework.boot:spring-boot-starter-data-jpa' implementation 'org.springframework.boot:spring-boot-starter-validation' implementation 'mysql:mysql-connector-java:8.0.32' compileOnly 'org.projectlombok:lombok' developmentOnly 'org.springframework.boot:spring-boot-devtools' annotationProcessor 'org.springframework.boot:spring-boot-configuration-processor' annotationProcessor 'org.projectlombok:lombok' testImplementation 'org.springframework.boot:spring-boot-starter-test' } tasks.named('test') { useJUnitPlatform() } tasks.withType(JavaCompile) { options.annotationProcessorPath = configurations.compileClasspath }
修改说明:
- 移除手动添加的
spring-data-jpa、javax.persistence-api、jakarta.persistence-api、hibernate-core、hibernate-entitymanager,这些组件已由spring-boot-starter-data-jpa自动引入,版本与Spring Boot 3.0.5完全兼容(默认使用Hibernate 6.1.x,适配Jakarta EE 9)。 - 将
spring-boot-starter-validation版本统一为3.0.5,避免与Spring Boot 3.x版本冲突。
二、正确实现“关联电影的演员不可删除”约束
你的需求是:当Actor被关联到Movie时,禁止删除该Actor。推荐两种可靠实现方式:
方法1:外键约束(数据库原生支持,推荐)
通过配置外键的删除规则为RESTRICT,让数据库直接阻止删除关联了电影的演员。
修改Movie类的@ManyToMany关联配置:
import jakarta.persistence.*; import lombok.AllArgsConstructor; import lombok.Getter; import lombok.NoArgsConstructor; import lombok.Setter; import java.time.LocalDate; import java.util.HashSet; import java.util.Set; @Entity @Table(name = "movies", uniqueConstraints = @UniqueConstraint(columnNames = {"title", "releaseDate"})) public class Movie extends Media { @Column(nullable = false) private String title; @Column(nullable = false) private LocalDate releaseDate; @ManyToMany(fetch = FetchType.LAZY) @JoinTable( name = "movie_actor", joinColumns = @JoinColumn( name = "movie_id", foreignKey = @ForeignKey( ConstraintMode.CONSTRAINT, name = "fk_movie", foreignKeyDefinition = "FOREIGN KEY (movie_id) REFERENCES movies(id) ON DELETE CASCADE" ) ), inverseJoinColumns = @JoinColumn( name = "actor_id", foreignKey = @ForeignKey( ConstraintMode.CONSTRAINT, name = "fk_actor", foreignKeyDefinition = "FOREIGN KEY (actor_id) REFERENCES actors(id) ON DELETE RESTRICT" ) ), uniqueConstraints = {@UniqueConstraint(columnNames = {"movie_id", "actor_id"})} ) private Set<Actor> actors = new HashSet<>(); // getter、setter等方法 }
也可以直接在Actor实体的关联字段上配置:
@Entity @Table(name = "actors") public class Actor { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; // 其他字段 @ManyToMany(mappedBy = "actors", fetch = FetchType.LAZY) @OnDelete(action = OnDeleteAction.RESTRICT) // Hibernate自动生成ON DELETE RESTRICT的外键约束 private Set<Movie> movies = new HashSet<>(); }
方法2:@Check约束(需数据库支持)
如果要使用@Check,需将约束添加到Actor的表上,同时开启Hibernate生成Check约束的配置:
- 在
application.properties中添加配置:
spring.jpa.hibernate.ddl-auto=update spring.jpa.properties.hibernate.check_constraints=true
- 修改Actor实体:
@Entity @Table(name = "actors", constraints = @Check(constraints = "NOT EXISTS(SELECT * FROM movie_actor ma WHERE ma.actor_id = id)")) public class Actor { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; // 其他字段及关联关系 }
注意:此方法依赖数据库对Check约束的支持(如PostgreSQL完全支持,MySQL 8.0.16+才会生效Check约束,旧版本仅语法兼容),因此更推荐方法1的外键约束方案。
内容的提问来源于stack exchange,提问作者WowBow
相关产品推荐
相关产品推荐

