Confusion: @Notnull VS. @Column(Nullable = False) with JPA and Hibernate

Confusion: @NotNull vs. @Column(nullable = false) with JPA and Hibernate

@NotNull is a JSR 303 Bean Validation annotation. It has nothing to do with database constraints itself. 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. @Column(nullable = false) is the JPA way of declaring a column to be not-null. I.e. the former is intended for validation and the latter for indicating database schema details. You're just getting some extra (and welcome!) help from Hibernate on the validation annotations.

Annotations @Column( nullable = false ) vs @NotNull difference

@Column is database related. If you auto-create a database schema from your Java code, the nullable=false will make sure to create a NOT NULL column, which should be useful if there are other applications accessing your database. Also, your app may check this constraint just before sending data to the database.

@NotNull is Java related. Java will throw exceptions when this attribute is not set. No database context necessary.

Both annotations sound alike, but serve two different purposes. There might be libraries which automatically infer one annotation from the other, but you can always use both annotations. When you do, @NotNull will be checked BEFORE @Column.

@DataJpaTest ignores @Column(unique = true) and @Column(nullable = false)

The @DataJpaTest makes your test @Transactional which means everything in the test runs in a transaction and will rollback after the test. That combined with the default flush mode of AUTO (which will flush automatically on commit) makes it that no actual SQL will be issues to the database in your test. (Enabling query logging would show this). With no SQL to the database no constraints will trigger and thus no exception.

To fix you can do 2 things.

  1. Use saveAndFlush instead of save, as that will flush changes to the database and thus issue SQL.
  2. Inject the TestEntityManager and after all your calls, before the asserts, call the flush method so synchronize the changes to the database and issue the SQL.

Either will work as it will trigger the flushing of the changes.

Why should I specify @Column( nullable = false )?

Better error messages and error handling, especially if you also add the JSR303 @NotNull annotation.

If you create the column as NOT NULL but don't tell JPA it's not null, JPA will assume that null values are OK. When you try to save an object with nulls, it'll proceed to send that to the DB and you'll get a DB level error. This increases log spam in the database and it's much harder to determine from the error which column(s) of which table(s) were the problem, let alone map them back to their JPA names.

If you annotate them as not null, JPA will throw an exception before saving, avoiding DB log spam and usually giving you a better error. In particular, if your JPA provider supports JSR303 and either translates nullable=false into @NotNull internally or you've added @NotNull too, it'll give you a data structure you can examine to see exactly what fields of what objects were rejected for what reasons, along with customisable templated error messages.

That's why you should tell JPA about NOT NULL fields. That, and it's easier for others working on your code to understand without also having to read the DB schema.

NotNull not working, Column(nullable = false) working

@NotNull is a JSR 303 Bean Validation annotation. It has nothing to do with database constraints itself. This annotation is intended for validation. @Column(nullable = false) is the way of declaring a column to be not-null. This last annotation is intended for indicating database schema details



Related Topics



Leave a reply



Submit