Hibernate Tips: What’s the difference between @Column(nullable = false) and @NotNull


Take your skills to the next level!

The Persistence Hub is the place to be for every Java developer. It gives you access to all my premium video courses, monthly Java Persistence News, monthly coding problems, and regular expert sessions.



Hibernate Tips is a series of posts in which I describe a quick and easy solution for common Hibernate questions. If you have a question for a future Hibernate Tip, please post a comment below.

Question:

One of my entity attributes shall not be null. There seem to be 2 different ways to ensure that. I can either annotate it with @Column(nullable=false) or with @NotNull.

What’s the difference between these 2 options? Which one should I use?

Solution:

Both approaches seem to create a similar result, but there are important differences between them. The 3 most important ones are:

  1. The specification that defines the annotation and the required dependencies.
  2. Where the check gets performed.
  3. The point in time when the check gets performed.

Before I address all 3 of them, let me quickly show you the example entity that I will use in this Hibernate Tip.

A Simple Example Entity

All examples in this tip, use the Book entity. As you can see in the following code snippet, on the titleNullable attribute, I prevent null values by setting the nullable attribute of the @Column annotation to false. On the titleNotNull attribute, I use the @NotNull annotation.

@Entity
public class Book {

	@Id
	@GeneratedValue
	private Long id;

	@Column(nullable = false)
	private String titleNullable;

	@NotNull
	private String titleNotNull;

	private LocalDate publishingDate;
	
	... 
}

If you let Hibernate generate the database schema, which you should not do for a production system, there is no difference between the two columns.

CREATE TABLE public.book
(
    id bigint NOT NULL,
    publishingdate date,
    titlenotnull character varying(255) COLLATE pg_catalog."default" NOT NULL,
    titlenullable character varying(255) COLLATE pg_catalog."default" NOT NULL,
    version integer NOT NULL,
    CONSTRAINT book_pkey PRIMARY KEY (id)
)

So, what’s different?

Difference 1: The defining specification

The first difference between the two approaches are the specifications that define these two annotations and due to that the required dependencies.

The @Column annotation is part of the JPA specification, and you already use all required dependencies. The @NotNull annotation gets defined by the BeanValidation specification. You need to add a dependency to the Hibernate Validator project, or to any other implementation of the BeanValidation specification.

Difference 2: The system that performs the check

The @NotNull annotation triggers a validation by the BeanValidation implementation when a pre-update or a pre-persist lifecycle event gets triggered. So, the validation happens within your Java application.

Hibernate doesn’t perform any validation if you annotate an attribute with @Column(nullable = false). This annotation only adds a not null constraint to the database column, if Hibernate creates the database table definition. The database then checks the constraint, when you insert or update a record.

This might seem like a minor difference, but it’s essential. The @Column(nullable = false) annotation has no effect if Hibernate doesn’t generate the table definition. That means that you need to pay extra attention to your database script if you create your database schema with Flyway or Liquibase.

Difference 3: The time when the check gets performed

As explained before, the @NotNull annotation tells your BeanValidation implementation to check that the attribute is not null. This happens when the pre-update or pre-persist lifecycle event gets processed. If the validation fails, Hibernate will not execute any SQL statement.

The @Column(nullable = false) annotation only adds a not null constraint to the table definition. Hibernate or any other framework will not perform any validation on the entity attribute. Hibernate just executes the SQL UPDATE statement, and the database will validate the constraint. If the entity attribute is null, the SQL statement will fail.

Which approach should you use?

I hope that the answer to this question has become apparent after you read this tip. You should always use the @NotNull annotation, which is defined by the BeanValidation specification. It configures a validation step that gets performed before Hibernate executes the SQL statement.

It might look like JPA’s @Column annotation achieves the same result, but that’s only the case if Hibernate generates the table definition and adds the not null constraint. Database constraints are an important tool to ensure data consistency, but you shouldn’t rely on them in your Java application.

Learn more:

If you liked this article, you might also be interested in:

Hibernate Tips Book

Get more recipes like this one in my new book Hibernate Tips: More than 70 solutions to common Hibernate problems.

It gives you more than 70 ready-to-use recipes for topics like basic and advanced mappings, logging, Java 8 support, caching, and statically and dynamically defined queries.

Get it now!

11 Comments

  1. Thank you! Very helpful!

    I am curious to read more about this: "If you let Hibernate generate the database schema, which you should not do for a production system", did you write anything about this?
    I am working on a small Spring Boot + Hibernate + MySQL + Angular application and I want to follow the rules and best practices.

  2. Avatar photo ashkanariaashkan says:

    Many Thanks

    1. Avatar photo Thorben Janssen says:

      Thanks for commenting 🙂

  3. Can I use them both on same field?
    If yes, what would be auto-generated in scheme creation SQL script?

    1. Avatar photo Thorben Janssen says:

      Yes, you can use both of them on the same field.
      Hibernate auto-generates the same CREATE TABLE statement for @Column(nullable = false) and @NotNull. So, annotating it with both of them will not change the generated statement.

  4. Avatar photo Binh Thanh Nguyen says:

    Thanks, nice explanation!

    1. Avatar photo Thorben Janssen says:

      Thanks for reading 🙂

  5. Avatar photo AKHLAQUE KHAN says:

    Great effort to avail valuable concepts…

    Regards

  6. Pre-update and pre-persist only? And what about reads? What if a database does not have ‘not null’ constraint and I select a bean with @NotNull annotated feld and it has null value. Will be exception raised?

    1. Avatar photo Thorben Janssen says:

      Hi Sergey,

      The BeanValidation implementation gets automatically triggered before each persist and update operation. You can also trigger it before a remove operation. Read operations don’t trigger any validation.
      So, if your database contains any invalid values, you wouldn’t recognize that until you try to update an entity that contains an invalid value.

      Regards,
      Thorben

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.