5

According to hibernate validator reference documentation - Section 11.1.1. Database schema-level validation (https://docs.jboss.org/hibernate/stable/validator/reference/en-US/html_single/#validator-checkconstraints-db),

Out of the box, Hibernate ORM will translate the constraints you have defined for your entities into mapping metadata. For example, if a property of your entity is annotated @NotNull, its columns will be declared as not null in the DDL schema generated by Hibernate ORM.

But when I annotate my fields with @NotNull, I'm not getting the schema level constraints automatically.

I tried setting Environment.HBM2DDL_AUTO to update and create but neither one works in generating the database constraints.

Even though hibernate by default has the hibernate.validator.apply_to_ddl set to true, I even tried setting that manually -

settings.put("hibernate.validator.apply_to_ddl", true);

But none of these options seems to work for me.

My domain class

package com.praveen.domain;

import javax.persistence.Entity;
import javax.validation.constraints.NotNull;

import lombok.Data;

@Entity
@Data
public class Stakeholder extends MyPersistent {

    @NotNull
    private String clientCode;

    @NotNull
    private String gender;
}

MyPersistent class

package com.praveen.domain;

import java.io.Serializable;

import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.MappedSuperclass;

import lombok.Getter;
import lombok.Setter;

@MappedSuperclass
@Getter
@Setter
public class MyPersistent implements Serializable {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
}

The code I'm using to get the session factory is

    private static SessionFactory getSessionFactory() {
        if (sessionFactory == null) {
            try {
                StandardServiceRegistryBuilder registryBuilder = new StandardServiceRegistryBuilder();

                Map<String, Object> settings = new HashMap<>();
                settings.put(Environment.DRIVER, Driver.class.getName());
                settings.put(Environment.URL, "jdbc:mysql://localhost:3306/hibernate_test?"
                        + "zeroDateTimeBehavior=CONVERT_TO_NULL&"
                        + "createDatabaseIfNotExist=true&"
                        + "useSSL=true&"
                        + "verifyServerCertificate=false&"
                        + "autoReconnect=true");
                settings.put(Environment.USER, "root");
                settings.put(Environment.PASS, "");
                settings.put(Environment.DIALECT, MySQL55Dialect.class);
                settings.put(Environment.HBM2DDL_AUTO, "update");
                settings.put(Environment.SHOW_SQL, false);

                // HikariCP settings
                settings.put("hibernate.hikari.connectionTimeout", "20000");
                settings.put("hibernate.hikari.minimumIdle", "5");
                settings.put("hibernate.hikari.maximumPoolSize", "20");
                settings.put("hibernate.hikari.idleTimeout", "300000");

                registryBuilder.applySettings(settings);
                registry = registryBuilder.build();
                MetadataSources sources = new MetadataSources(registry);
                sources.addAnnotatedClass(Stakeholder.class);

                Metadata metadata = sources.getMetadataBuilder().build();
                sessionFactory = metadata.getSessionFactoryBuilder().build();
            } catch (Exception e) {
                e.printStackTrace();
                shutdown();
            }
        }
        return sessionFactory;
    }
Praveen Fernando
  • 319
  • 3
  • 13
  • @Kayaman, I referred that post before I posted my own, and it clearly states "As Hibernate is the reference implementation of JSR 303, however, it intelligently picks up on these constraints and translates them into database constraints for you, so you get two for the price of one". But for some reason it didn't work out for me, and I'm asking why. – Praveen Fernando Jul 10 '18 at 06:00
  • To be clear, is this a case where you're creating a new schema from a blank database, or are you trying to get Hibernate to apply the constraints to an existing schema? – chrylis -cautiouslyoptimistic- Jul 10 '18 at 06:54
  • I tried both scenarios but the result is the same – Praveen Fernando Jul 10 '18 at 06:59

2 Answers2

2

It was a silly mistake on my side as I hadn't included the javax.el dependency and its implementation in the pom.xml.

Interestingly enough, I didn't get the java.lang.NoClassDefFoundError: javax/el/ELManager error by then as I hadn't written any code to initialize the ValidatorFactory by Validation.buildDefaultValidatorFactory().

As soon as I wrote the code and used ValidatorFactory, I got the NoClassDefFoundError and found out I was missing the javax.el dependency.

So finally I was able to resolve the NoClassDefFoundError error as well as the non translation issue of validation annotations to database constraints in schema generation by adding the below dependencies.

    <dependency>
        <groupId>javax.el</groupId>
        <artifactId>javax.el-api</artifactId>
        <version>3.0.0</version>
    </dependency>

    <dependency>
        <groupId>org.glassfish</groupId>
        <artifactId>javax.el</artifactId>
        <version>3.0.0</version>
    </dependency>
Praveen Fernando
  • 319
  • 3
  • 13
1

You should use @Column(nullable = false)

@NotNull is for Bean validation, not schema constraints, and if you are using an older version of hibernate @NotNull will not be translated to column constraint

pixelatedCat
  • 312
  • 5
  • 17