英文:
jakarta.persistence.Check constraint not working
问题
I have the following Movie class in a Spring Boot project that holds a list of actors. I wanted to make sure an actor won't be deleted if it's part of a movie, and I want to enforce this constraint on a database level using JPA/Hibernate. However, when I import jakarta.persistence.Check
, the compiler is not recognizing it even though I have the right dependency in Gradle. I assume this is a versioning issue, but I couldn't resolve it.
import jakarta.persistence.*;
import jakarta.persistence.Check;
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"),
inverseJoinColumns = @JoinColumn(name = "actor_id"),
uniqueConstraints = {@UniqueConstraint(columnNames = {"movie_id", "actor_id"})},
foreignKey = @ForeignKey(name = "fk_movie"),
inverseForeignKey = @ForeignKey(name = "fk_actor"),
// add check constraint to ensure actor is not deleted if part of any movie
constraints = @Check(constraints = "NOT EXISTS(SELECT * FROM movie_actor ma WHERE ma.actor_id = id)")
)
private Set<Actor> actors = new HashSet<>();
}
Here is my build.gradle
file:
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()
//jcenter()
}
dependencies {
implementation 'org.springframework.data:spring-data-jpa:3.0.4'
implementation 'javax.persistence:javax.persistence-api:2.2'
implementation 'jakarta.persistence:jakarta.persistence-api:3.1.0'
implementation 'jakarta.validation:jakarta.validation-api:3.0.2'
implementation 'org.springframework.boot:spring-boot-starter-validation:2.6.3'
implementation 'org.springframework.boot:spring-boot-starter-web'
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
implementation 'mysql:mysql-connector-java:8.0.32'
implementation 'org.hibernate:hibernate-core:5.5.7.Final'
implementation 'org.hibernate:hibernate-entitymanager:5.5.7.Final'
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
}
英文:
I have the following Movie class in a Spring Boot project that holds list of actors. I wanted to make sure an actor wont be deleted if its part of a movie and I want to enforce this constraint on a database level by JPA/Hibernate. However when I import jakarta.persistence.Check
the complier is not recognizing it even if I had the right dependency in gradle. I assume this is versioning issue but I couldn't get it resolved.
import jakarta.persistence.*;
import jakarta.persistence.Check;
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"),
inverseJoinColumns = @JoinColumn(name = "actor_id"),
uniqueConstraints = {@UniqueConstraint(columnNames = {"movie_id", "actor_id"})},
foreignKey = @ForeignKey(name = "fk_movie"),
inverseForeignKey = @ForeignKey(name = "fk_actor"),
// add check constraint to ensure actor is not deleted if part of any movie
constraints = @Check(constraints = "NOT EXISTS(SELECT * FROM movie_actor ma WHERE ma.actor_id = id)")
)
private Set<Actor> actors = new HashSet<>();
}
Here is my gradle.build file:
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()
//jcenter()
}
dependencies {
implementation 'org.springframework.data:spring-data-jpa:3.0.4'
implementation 'javax.persistence:javax.persistence-api:2.2'
implementation 'jakarta.persistence:jakarta.persistence-api:3.1.0'
implementation 'jakarta.validation:jakarta.validation-api:3.0.2'
implementation 'org.springframework.boot:spring-boot-starter-validation:2.6.3'
implementation 'org.springframework.boot:spring-boot-starter-web'
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
implementation 'mysql:mysql-connector-java:8.0.32'
implementation 'org.hibernate:hibernate-core:5.5.7.Final'
implementation 'org.hibernate:hibernate-entitymanager:5.5.7.Final'
/*
*/
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
}
答案1
得分: 3
Jakarta Persistence API从未定义@Check
注解。因此,jakarta.persistence.Check
既在2.3规范中也不在3.x规范中存在。最新规范可在此处找到,源代码在这里。
我假设您想要使用org.hibernate.annotations.Check
。
有关更多信息,请查看此链接:https://docs.jboss.org/hibernate/orm/5.5/userguide/html_single/Hibernate_User_Guide.html#schema-generation-database-checks。
最后,我想指出代码的一些重要部分。
- Hibernate Entitymanager 5.5.7已经进入了生命周期的终点。这个版本不再受支持。我强烈建议升级此依赖项。
spring-data-jpa:3.0.4
具有一个可选依赖项hibernate-core:6.1.4.Final
。这是因为我建议使用Hibernate 6.x。- 您在依赖项中定义了两个不兼容的JPA API:
javax.persistence:javax.persistence-api:2.2
和jakarta.persistence:jakarta.persistence-api:3.1.0
。Spring Framework 6和Spring Boot 3都完全兼容Jakarta EE 9。在Jakarta堆栈上使用任何javax.*
依赖项可能会引发问题。
英文:
Jakarta Persistence API have never defined @Check
annotation. So, jakarta.persistence.Check
doesn't exsist neither in 2.3 nor 3.x specification. The latest specification is available here and the source code is here.
I assume you would like to use org.hibernate.annotations.Check
For further information, follow this link: https://docs.jboss.org/hibernate/orm/5.5/userguide/html_single/Hibernate_User_Guide.html#schema-generation-database-checks.
Finally, I'd like to point out some important parts of this code.
- Hibernate Entitymanager 5.5.7 reached the End Of Life phase. This version is no longer supported. I strongly recommend to upgrade this dependency.
spring-data-jpa:3.0.4
has an optional dependencyhibernate-core:6.1.4.Final
. That's because I recommend use Hibernate 6.x.- You've defined two incompatible JPA API in the dependencies:
javax.persistence:javax.persistence-api:2.2
andjakarta.persistence:jakarta.persistence-api:3.1.0
Both Spring Framework 6 and Spring Boot 3 are fully Jakarta EE 9 compatible. On Jakarta stack using anyjavax.*
dependency may cause problems.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论