Matías Santurio
Matías Santurio

Reputation: 255

@NotNull not working on embedded classes, using hibernate

I have the following two Address, User classes:

import javax.persistence.Embeddable;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;

@Embeddable
public class Address {
    @NotNull
    @Size(max = 50)
    private String street;
}
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
import javax.validation.Valid;
import javax.validation.constraints.NotNull;

@Entity
@Table(name = "USERS")
public class User {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @NotNull
    private String username;

    @Valid
    private Address homeAddress;
}

And this is generating the following MySQL table:

CREATE TABLE `USERS` (
  `id` bigint NOT NULL AUTO_INCREMENT,
  `street` varchar(50) DEFAULT NULL,
  `username` varchar(255) NOT NULL,
  PRIMARY KEY (`id`)
)

As you can see, the @NotNull constraint worked for the username field, and the @Size(max = 50) constraint worked for the embedded class. However, the @NotNull constraint on the embedded class doesn't seem to working, what am I missing?

The pom.xml, in case it's relevant:

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
    http://maven.apache.org/maven-v4_0_0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.manning.javapersistence</groupId>
    <artifactId>mapping-value-types</artifactId>
    <packaging>jar</packaging>
    <version>1.0-SNAPSHOT</version>
    <name>mapping-value-types</name>
    <url>http://maven.apache.org</url>

    <build>
        <plugins>
            <plugin>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.10.1</version>
                <configuration>
                    <source>17</source>
                    <target>17</target>
                </configuration>
            </plugin>
            <plugin>
                <artifactId>maven-surefire-plugin</artifactId>
                <version>2.22.2</version>
                <configuration>
                    <includes>
                        <include>**/*.java</include>
                    </includes>
                </configuration>
            </plugin>
        </plugins>
    </build>

    <dependencies>
        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-entitymanager</artifactId>
            <version>5.6.9.Final</version>
        </dependency>
        <dependency>
            <groupId>org.junit.jupiter</groupId>
            <artifactId>junit-jupiter-engine</artifactId>
            <version>5.8.2</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.29</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.data</groupId>
            <artifactId>spring-data-jpa</artifactId>
            <version>2.7.0</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-test</artifactId>
            <version>5.3.20</version>
        </dependency>
        <dependency>
            <groupId>org.glassfish</groupId>
            <artifactId>javax.el</artifactId>
            <version>3.0.0</version>
        </dependency>
        <dependency>
            <groupId>javax.validation</groupId>
            <artifactId>validation-api</artifactId>
            <version>2.0.1.Final</version>
        </dependency>
        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-validator</artifactId>
            <version>6.2.3.Final</version>
        </dependency>
    </dependencies>

</project>

Upvotes: 0

Views: 532

Answers (2)

Claus Polanka
Claus Polanka

Reputation: 103

In the recently published book: Java Persistence with Spring Data and Hibernate, the authors mention the following:

Problem: Hibernate Validator doesn’t generate NOT NULL constraints At the time of writing, an open flaw remains with Hibernate Validator: Hibernate won’t map @NotNull constraints on embeddable component properties to NOT NULL constraints when generating the database schema. Hibernate will only use @NotNull on the components’ properties at runtime for Bean Validation. We have to map the property with @Column(nullable = false) to generate the constraint in the schema. The Hibernate bug database is tracking this problem as HVAL-3 (see http://mng.bz/lR0R).

Upvotes: 0

Nikos Paraskevopoulos
Nikos Paraskevopoulos

Reputation: 40318

The reason Hibernate overrides your setting of @NotNull on Address.street when generating the table for the User entity is that the field User.homeAddress itself is nullable. This means that you have specified that it is perfectly fine to pass a User object with null homeAddress to Hibernate. And Hibernate (JPA generally I think) will deal with it by making all the fields of the embeddable nullable.

Maybe you can try annotating the User.homeAddress field as @NotNull -or- orverride the embedded column definition with @Embedded @AttributeOverrides({@AttributeOverride(name="street", column=@Column(..., nullable=false))}).

Upvotes: 1

Related Questions