Confusione: @NotNull vs. @Column (nullable = false) con JPA e Hibernate


242
  1. Quando compaiono su un campo / getter di un @Entity, qual è la differenza tra loro? (Persisto l'Entità attraverso l' ibernazione ).

  2. A quale framework e / o specifica appartiene ciascuno di essi?

  3. @NotNullsi trova all'interno javax.validation.constraints. Nel javax.validation.constraints.NotNulljavadoc dice

    L'elemento annotato non deve essere nullo

    ma non parla della rappresentazione dell'elemento nel database, quindi perché dovrei aggiungere il vincolo nullable=falsealla colonna?

Risposte:


328

@NotNullè un'annotazione di convalida bean JSR 303 . Non ha nulla a che fare con i vincoli del database stesso. Poiché Hibernate è l'implementazione di riferimento di JSR 303, tuttavia, raccoglie in modo intelligente questi vincoli e li traduce in vincoli di database per te, quindi ne ottieni due al prezzo di uno. @Column(nullable = false)è il modo JPA di dichiarare una colonna non nulla. Vale a dire il primo è destinato alla convalida e il secondo per indicare i dettagli dello schema del database. Stai solo ricevendo un aiuto extra (e benvenuto!) Da Hibernate sulle annotazioni di convalida.


2
Grazie! Quindi, se voglio che la mia persistenza JPA non sia legata all'implementazione di Hibernate (ovvero cambio a EJB3), allora devo usare entrambe le annotazioni (per vietare null sia nel campo che nella sua colonna)?
rapt

3
Non lo so. Non ci sono specifiche che dicono che un provider JPA deve riconoscere le annotazioni JSR 303, ma ciò non significa che altri provider non lo facciano. Non posso dire se qualcuno lo fa o no.
Ryan Stewart,

7
I fornitori di JPA non sono tenuti a fornire l'implementazione JSR303 ma sono conformi alle specifiche richieste per fornire la possibilità di integrarsi con qualsiasi implementazione JSR303 di terze parti. Quindi, sebbene Hibernate fornisca JSR303, per qualsiasi motivo potresti decidere di non usare il loro e andare con qualcun altro o usare un'implementazione JPA come openJPA e usare qualcun altro per fornire JSR303. Inoltre, l'implementazione JPA di Hibernate è anche EJB3. "se voglio che la mia persistenza dell'APP non sia legata all'implementazione di Hibernate (ovvero cambio a EJB3)", l'APP fa parte delle specifiche EJB3.
Shahzeb,

5
@Shahzeb: la domanda non riguarda chi supporta / fornisce la convalida JSR 303. Si tratta di che ORM (s) riconosce JSR 303 annotazioni come @NotNull, @Size, @Min, @Max, ecc, e tradurre quelle in vincoli del database.
Ryan Stewart,

1
Sì, ma il mio commento è valido nel contesto di ciò che OP ha chiesto nel commento successivo che non conoscevi.
Shahzeb,

18

Le versioni più recenti del provider JPA ibernazione applicano i vincoli di convalida del bean (JSR 303) come @NotNullDDL per impostazione predefinita (grazie alle hibernate.validator.apply_to_ddl propertyimpostazioni predefinite su true). Ma non vi è alcuna garanzia che altri provider JPA lo facciano o abbiano la possibilità di farlo.

È necessario utilizzare le annotazioni di convalida del bean, @NotNullad esempio, per garantire che le proprietà del bean siano impostate su un valore null, durante la convalida dei bean Java nella JVM (ciò non ha nulla a che fare con i vincoli del database, ma nella maggior parte dei casi dovrebbe corrispondere a essi).

È inoltre necessario utilizzare l'annotazione JPA come @Column(nullable = false)per fornire suggerimenti al provider jpa per generare il DDL corretto per la creazione di colonne di tabella con i vincoli del database desiderati. Se è possibile o si desidera fare affidamento su un provider JPA come Hibernate, che applica i vincoli di convalida del bean a DDL per impostazione predefinita, è possibile ometterli.


10

Interessante notare che tutte le fonti sottolineano che @Column (nullable = false) viene utilizzato solo per la generazione DDL.

Tuttavia, anche se non è presente alcuna annotazione @NotNull e l'opzione hibernate.check_nullability è impostata su true, Hibernate eseguirà la convalida delle entità da persistere.

Genererà PropertyValueException dicendo che "la proprietà not-null fa riferimento a un valore null o transitorio", se gli attributi nullable = false non hanno valori, anche se tali restrizioni non sono implementate nel livello del database.

Ulteriori informazioni sull'opzione hibernate.check_nullability sono disponibili qui: http://docs.jboss.org/hibernate/orm/5.0/userguide/html_single/Hibernate_User_Guide.html#configurations-mapping .


7

L' @Columnannotazione dell'APP

L' nullableattributo @Columndell'annotazione ha due scopi:

  • viene utilizzato dallo strumento di generazione dello schema
  • viene utilizzato da Hibernate durante lo svuotamento del contesto di persistenza

Strumento di generazione dello schema

Lo strumento di generazione dello schema HBM2DDL traduce l' @Column(nullable = false)attributo di entità in un NOT NULLvincolo per la colonna della tabella associata durante la generazione dell'istruzione CREATE TABLE.

Come ho spiegato nella Guida dell'utente di Hibernate , è meglio utilizzare uno strumento come Flyway invece di fare affidamento sul meccanismo HBM2DDL per generare lo schema del database.

Flusso di contesto di persistenza

Durante lo svuotamento del contesto di persistenza, Hibernate ORM utilizza anche l' @Column(nullable = false)attributo entità:

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

Se la convalida fallisce, Hibernate lancerà a PropertyValueExceptione impedisce che le istruzioni INSERT o UPDATE vengano eseguite in modo necessario:

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]
        );    
}

Per maggiori dettagli sul funzionamento del meccanismo di scarico Hibernate, consulta questo articolo .

The Bean Validation @NotNullAnnotation

L' @NotNullannotazione è definita da Bean Validation e, proprio come Hibernate ORM è l'implementazione JPA più popolare, l'implementazione Bean Validation più popolare è il framework Hibernate Validator .

Quando si utilizza Hibernate Validator insieme a Hibernate ORM, Hibernate Validator lancerà a ConstraintViolationdurante la convalida dell'entità.


Perché affermi che flyway è meglio che generare schema?
Andronico

1
Questa è una buona osservazione. Ho aggiornato la risposta con un link di riferimento.
Vlad Mihalcea,

Grazie per il riferimento e ottima risposta!
Andronico
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.