Search code examples
javahibernatejpajakarta-eeconstraints

jakarta.persistence.Check constraint not working


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
}

Solution

  • 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.

    1. Hibernate Entitymanager 5.5.7 reached the End Of Life phase. This version is no longer supported. I strongly recommend to upgrade this dependency.
    2. spring-data-jpa:3.0.4 has an optional dependency hibernate-core:6.1.4.Final. That's because I recommend use Hibernate 6.x.
    3. You've defined two incompatible JPA API in the dependencies: javax.persistence:javax.persistence-api:2.2 and jakarta.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 any javax.* dependency may cause problems.