253
  1. When they appear on a field/getter of an @Entity, what is the difference between them? (I persist the Entity through Hibernate).

  2. What framework and/or specification each one of them belongs to?

  3. @NotNull is located within javax.validation.constraints. In the javax.validation.constraints.NotNull javadoc it says

    The annotated element must not be null

    but it does not speak of the element's representation in the database, so why would I add the constraint nullable=false to the column?

Vlad Mihalcea
  • 103,297
  • 39
  • 432
  • 788
rapt
  • 10,528
  • 29
  • 92
  • 134

4 Answers4

338

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

Chakkakuru
  • 77
  • 1
  • 8
Ryan Stewart
  • 115,853
  • 19
  • 167
  • 192
  • 2
    Thanks! So if I want my JPA persistence not to be tied to the Hibernate implementation (i.e. change to EJB3) then I have to use both annotations (to prohibit null in both the field and its column)? – rapt Sep 16 '11 at 02:54
  • 3
    I don't know. There's no specification that says a JPA provider must recognize JSR 303 annotations, but that doesn't mean that other providers don't. I can't say whether any does or doesn't. – Ryan Stewart Sep 16 '11 at 02:59
  • 7
    JPA providers are not required to provide JSR303 implementation but are as per specification required to provide the ability to integrate with any third party JSR303 implementation. So while Hibernate does provide JSR303 you could for whatever reason decide not to use theirs and go with somebody else or use a JPA implementation like openJPA and use somebody else to provide JSR303.Also note Hibernate's JPA implementaion is Also EJB3.It is incorrect to say 'if I want my JPA persistence not to be tied to the Hibernate implementation (i.e. change to EJB3)' JPA is part of EJB3 specification. – Shahzeb Sep 16 '11 at 03:19
  • 5
    @Shahzeb: The question isn't about who supports/provides JSR 303 validation. It's about which ORM(s) recognize JSR 303 annotations like `@NotNull`, `@Size`, `@Min`, `@Max`, etc., and translate those into database constraints. – Ryan Stewart Sep 16 '11 at 03:30
  • 1
    Yes but my comment is valid in the context of what OP asked in the subsequent comment which you did not know. – Shahzeb Sep 16 '11 at 03:35
  • @Shahzeb Thanks. I meant EJB3 RI. It contains an implementation of JPA. I did no get what you meant by "Also note Hibernate's JPA implementation is Also EJB3"? It's only a subset of EJB3 so it's not EJB3. – rapt Sep 16 '11 at 03:43
  • @rapt Yes that correct . It is part of EJB3 .EJB3 is not one single thing. – Shahzeb Sep 16 '11 at 03:48
  • @Shahzeb: I don't understand how your comment answers the follow-up question. As far as I can tell, you're not indicating whether anything besides Hibernate supports the features under discussion here. For instance, you mentioned OpenJPA: does OpenJPA read JSR 303 annotations and create database constraints from them? – Ryan Stewart Sep 16 '11 at 04:46
  • Really not interested in this push and shove but read your first comment[not the answer first comment] then read my comment and if you still can not work it out print it and take it to some third person. May be someone from community can break this tie and if majority say what I said did not make sense in the context I will delete it.It's okay Ryan you do not need to know every thing it is your answer do not be insecure. – Shahzeb Sep 16 '11 at 04:59
  • @rapt: Do you understand what he's talking about? I'm still curious whether other JPA implementations support this. If you open a new question about it or something, let me know. I'd like to see the answers. – Ryan Stewart Sep 16 '11 at 12:02
  • @Ryan Stewart: I think you and Shahzeb both agree that JPA implementations don't necessarily have to implement JSR303. Also I wanted to note, what Hibernate does with `@NotNull` is not only supporting JSR303 but voluntarily expanding it to validating the DB representation (OK, it's an ORM framework, but not every object validation framework should even be aware of DB's). So in a future scenario where I use a different JSR303 implementation (which should be possible according to Shahzeb), I will need both annotations, to keep the current functionality (i.e. validating both object & DB column). – rapt Sep 16 '11 at 13:04
  • @Ryan Stewart: It's also what I read in the comments to the following answer: http://stackoverflow.com/questions/2725111/hibernate-onetoone-notnull/2726224#2726224 – rapt Sep 16 '11 at 13:08
  • what happen if the column was assigned null value? is it will getting error? – Diaz Pradiananto Jul 05 '12 at 08:18
  • @DiazPradiananto: Don't ask a new question in a comment, especially such an old one. Start a new SO question for it. – Ryan Stewart Jul 05 '12 at 15:10
18

The most recent versions of hibernate JPA provider applies the bean validation constraints (JSR 303) like @NotNull to DDL by default (thanks to hibernate.validator.apply_to_ddl property defaults to true). But there is no guarantee that other JPA providers do or even have the ability to do that.

You should use bean validation annotations like @NotNull to ensure, that bean properties are set to a none-null value, when validating java beans in the JVM (this has nothing to do with database constraints, but in most situations should correspond to them).

You should additionally use the JPA annotation like @Column(nullable = false) to give the jpa provider hints to generate the right DDL for creating table columns with the database constraints you want. If you can or want to rely on a JPA provider like Hibernate, which applies the bean validation constraints to DDL by default, then you can omit them.

Karl Richter
  • 6,271
  • 17
  • 57
  • 120
Sebastian Theek
  • 181
  • 1
  • 3
13

The JPA @Column Annotation

The nullable attribute of the @Column annotation has two purposes:

  • it's used by the schema generation tool
  • it's used by Hibernate during flushing the Persistence Context

Schema Generation Tool

The HBM2DDL schema generation tool translates the @Column(nullable = false) entity attribute to a NOT NULL constraint for the associated table column when generating the CREATE TABLE statement.

As I explained in the Hibernate User Guide, it's better to use a tool like Flyway instead of relying on the HBM2DDL mechanism for generating the database schema.

Persistence Context Flush

When flushing the Persistence Context, Hibernate ORM also uses the @Column(nullable = false) entity attribute:

new Nullability( session ).checkNullability( values, persister, true );

If the validation fails, Hibernate will throw a PropertyValueException, and prevents the INSERT or UPDATE statement to be executed needesly:

if ( !nullability[i] && value == null ) {
    //check basic level one nullablilty
    throw new PropertyValueException(
            "not-null property references a null or transient value",
            persister.getEntityName(),
            persister.getPropertyNames()[i]
        );    
}

The Bean Validation @NotNull Annotation

The @NotNull annotation is defined by Bean Validation and, just like Hibernate ORM is the most popular JPA implementation, the most popular Bean Validation implementation is the Hibernate Validator framework.

When using Hibernate Validator along with Hibernate ORM, Hibernate Validator will throw a ConstraintViolation when validating the entity.

Vlad Mihalcea
  • 103,297
  • 39
  • 432
  • 788
  • Why do you state that flyway is better than generating schema? – Andronicus Feb 29 '20 at 20:36
  • 1
    That's a good observation. I updated the answer with a reference link. – Vlad Mihalcea Feb 29 '20 at 21:12
  • Thanks for the reference and great answer! – Andronicus Feb 29 '20 at 21:55
  • Thanks for the great answer. Should i have both if i don't want to use schema generation tool or `@NotNull` is enough? and is `@Basic(optional=false)` the same as `@Column(nullable = false)`? – Arash May 27 '21 at 15:26
  • I never used `@NotNull` on any project I worked on. I don't think I've used `@Basic(optional=false)`. I'm not sure if Hibernate uses that one. I used `@Column(nullable = false)` only when the schema was generated. All in all, define your DB schema using FlywayDB, and validate on every layer: web, controller, service layer. – Vlad Mihalcea May 27 '21 at 18:42
12

Interesting to note, all sources emphasize that @Column(nullable=false) is used only for DDL generation.

However, even if there is no @NotNull annotation, and hibernate.check_nullability option is set to true, Hibernate will perform validation of entities to be persisted.

It will throw PropertyValueException saying that "not-null property references a null or transient value", if nullable=false attributes do not have values, even if such restrictions are not implemented in the database layer.

More information about hibernate.check_nullability option is available here: http://docs.jboss.org/hibernate/orm/5.0/userguide/html_single/Hibernate_User_Guide.html#configurations-mapping.