Confusion: @NotNull vs @Column (nullable = false) avec JPA et Hibernate

242
  1. Quand ils apparaissent sur un champ / getter d'un @Entity, quelle est la différence entre eux? (Je persiste l'entité à travers Hibernate ).

  2. À quel cadre et / ou spécification chacun d'eux appartient-il?

  3. @NotNullest situé à l'intérieur javax.validation.constraints. Dans le javax.validation.constraints.NotNulljavadoc, il est dit

    L'élément annoté ne doit pas être nul

    mais il ne parle pas de la représentation de l'élément dans la base de données, alors pourquoi ajouter la contrainte nullable=falseà la colonne?

ravi
la source

Réponses:

328

@NotNullest une annotation JSR 303 Bean Validation . Cela n'a rien à voir avec les contraintes de la base de données elle-même. Comme Hibernate est l'implémentation de référence de JSR 303, cependant, il reprend intelligemment ces contraintes et les traduit en contraintes de base de données pour vous, vous en obtenez donc deux pour le prix d'un. @Column(nullable = false)est le moyen JPA de déclarer une colonne comme non nulle. C'est-à-dire que le premier est destiné à la validation et le second à l'indication des détails du schéma de la base de données. Vous obtenez juste une aide supplémentaire (et bienvenue!) D'Hibernate sur les annotations de validation.

Ryan Stewart
la source
2
Merci! Donc, si je veux que ma persistance JPA ne soit pas liée à l'implémentation Hibernate (c'est-à-dire le changement vers EJB3), alors je dois utiliser les deux annotations (pour interdire null dans le champ et sa colonne)?
ravi
3
Je ne sais pas. Aucune spécification n'indique qu'un fournisseur JPA doit reconnaître les annotations JSR 303, mais cela ne signifie pas que les autres fournisseurs ne le font pas. Je ne peux pas dire si oui ou non.
Ryan Stewart
7
Les fournisseurs JPA ne sont pas tenus de fournir l'implémentation JSR303 mais doivent, conformément aux spécifications, fournir la capacité de s'intégrer à n'importe quelle implémentation JSR303 tierce. Ainsi, même si Hibernate fournit JSR303, vous pouvez pour une raison quelconque décider de ne pas utiliser le leur et aller avec quelqu'un d'autre ou utiliser une implémentation JPA comme openJPA et utiliser quelqu'un d'autre pour fournir JSR303. Notez également que l'implémentation JPA d'Hibernate est également EJB3. 'si je veux que ma persistance JPA ne soit pas liée à l'implémentation Hibernate (c'est-à-dire le changement vers EJB3)' JPA fait partie de la spécification EJB3.
Shahzeb
5
@Shahzeb: La question n'est pas de savoir qui prend en charge / fournit la validation JSR 303. Il est dont ORM (s) reconnaître JSR 303 annotations comme @NotNull, @Size, @Min, @Max, etc., et les traduire en contraintes de base de données.
Ryan Stewart,
1
Oui, mais mon commentaire est valable dans le contexte de ce que OP a demandé dans le commentaire suivant que vous ne saviez pas.
Shahzeb
18

Les versions les plus récentes du fournisseur JPA hibernate appliquent les contraintes de validation du bean (JSR 303) comme @NotNullDDL par défaut (grâce aux hibernate.validator.apply_to_ddl propertyvaleurs par défaut de true). Mais il n'y a aucune garantie que d'autres fournisseurs JPA le fassent ou aient même la capacité de le faire.

Vous devez utiliser des annotations de validation de bean, comme @NotNullpour vous assurer que les propriétés du bean sont définies sur une valeur non nulle, lors de la validation des beans java dans la JVM (cela n'a rien à voir avec les contraintes de base de données, mais dans la plupart des situations doit leur correspondre).

Vous devez en outre utiliser l'annotation JPA comme @Column(nullable = false)pour donner au fournisseur jpa des conseils pour générer la bonne DDL pour la création de colonnes de table avec les contraintes de base de données souhaitées. Si vous pouvez ou souhaitez compter sur un fournisseur JPA comme Hibernate, qui applique les contraintes de validation du bean à DDL par défaut, vous pouvez les omettre.

Sebastian Theek
la source
10

Il est intéressant de noter que toutes les sources soulignent que @Column (nullable = false) est utilisé uniquement pour la génération DDL.

Cependant, même s'il n'y a pas d'annotation @NotNull et que l'option hibernate.check_nullability est définie sur true, Hibernate effectuera la validation des entités à conserver.

Il lèvera PropertyValueException en disant que "la propriété non nulle fait référence à une valeur nulle ou transitoire", si les attributs nullable = false n'ont pas de valeurs, même si de telles restrictions ne sont pas implémentées dans la couche de base de données.

Plus d'informations sur l'option hibernate.check_nullability sont disponibles ici: http://docs.jboss.org/hibernate/orm/5.0/userguide/html_single/Hibernate_User_Guide.html#configurations-mapping .

Aleksandar Radulović
la source
7

L' @Columnannotation JPA

L' nullableattribut de l' @Columnannotation a deux objectifs:

  • il est utilisé par l'outil de génération de schéma
  • il est utilisé par Hibernate lors du vidage du contexte de persistance

Outil de génération de schéma

L'outil de génération de schéma HBM2DDL traduit l' @Column(nullable = false)attribut d'entité en une NOT NULLcontrainte pour la colonne de table associée lors de la génération de l' CREATE TABLEinstruction.

Comme je l'ai expliqué dans le Guide de l'utilisateur d'Hibernate , il est préférable d'utiliser un outil comme Flyway au lieu de s'appuyer sur le mécanisme HBM2DDL pour générer le schéma de base de données.

Rinçage du contexte de persistance

Lors du vidage du contexte de persistance, Hibernate ORM utilise également l' @Column(nullable = false)attribut d'entité:

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

Si la validation échoue, Hibernate lance un PropertyValueExceptionet empêche l'exécution forcée de l'instruction INSERT ou UPDATE:

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

Pour plus de détails sur le fonctionnement du mécanisme de vidage Hibernate, consultez cet article .

L' @NotNullannotation de validation du bean

L' @NotNullannotation est définie par Bean Validation et, tout comme Hibernate ORM est l'implémentation JPA la plus populaire, l'implémentation Bean Validation la plus populaire est le framework Hibernate Validator .

Lorsque vous utilisez Hibernate Validator avec Hibernate ORM, Hibernate Validator lance un ConstraintViolationlors de la validation de l'entité.

Vlad Mihalcea
la source
Pourquoi déclarez-vous que la voie de migration est meilleure que de générer un schéma?
Andronicus
1
Voilà une bonne observation. J'ai mis à jour la réponse avec un lien de référence.
Vlad Mihalcea
Merci pour la référence et la bonne réponse!
Andronicus