Confusión: @NotNull vs. @Column (nullable = false) con JPA e Hibernate

242
  1. Cuando aparecen en un campo / captador de un @Entity, ¿cuál es la diferencia entre ellos? (Persisto la Entidad a través de Hibernate ).

  2. ¿A qué marco y / o especificación pertenece cada uno de ellos?

  3. @NotNullSe encuentra dentro javax.validation.constraints. En el javax.validation.constraints.NotNulljavadoc dice

    El elemento anotado no debe ser nulo

    pero no habla de la representación del elemento en la base de datos, entonces, ¿por qué agregaría la restricción nullable=falsea la columna?

arrebatado
fuente

Respuestas:

328

@NotNulles una anotación JSR 303 Bean Validation . No tiene nada que ver con las restricciones de la base de datos en sí. Como Hibernate es la implementación de referencia de JSR 303, sin embargo, recoge de manera inteligente estas restricciones y las traduce en restricciones de base de datos para usted, por lo que obtiene dos por el precio de uno. @Column(nullable = false)es la forma JPA de declarar que una columna no es nula. Es decir, el primero está destinado a la validación y el segundo para indicar los detalles del esquema de la base de datos. Solo está recibiendo ayuda adicional (¡y bienvenida!) De Hibernate en las anotaciones de validación.

Ryan Stewart
fuente
2
¡Gracias! Entonces, si quiero que mi persistencia JPA no esté vinculada a la implementación de Hibernate (es decir, cambiar a EJB3), ¿entonces tengo que usar ambas anotaciones (para prohibir nulo tanto en el campo como en su columna)?
arrebatado el
3
No lo sé. No hay una especificación que diga que un proveedor de JPA debe reconocer las anotaciones JSR 303, pero eso no significa que otros proveedores no lo hagan. No puedo decir si alguno lo hace o no.
Ryan Stewart
77
Los proveedores de JPA no están obligados a proporcionar la implementación de JSR303, pero sí lo requieren según la especificación para proporcionar la capacidad de integrarse con cualquier implementación de JSR303 de terceros. Entonces, si bien Hibernate proporciona JSR303, por cualquier razón puede decidir no usar el suyo e ir con otra persona o usar una implementación JPA como openJPA y usar a alguien más para proporcionar JSR303.También tenga en cuenta que la implementación JPA de Hibernate es también EJB3.Es incorrecto decir 'si quiero que mi persistencia JPA no esté vinculada a la implementación de Hibernate (es decir, cambiar a EJB3)' JPA es parte de la especificación EJB3.
Shahzeb
55
@Shahzeb: La pregunta no se trata de quién apoya / proporciona la validación JSR 303. Se trata de los cuales ORM (s) reconoce JSR 303 anotaciones como @NotNull, @Size, @Min, @Max, etc, y los transforma en las limitaciones de bases de datos.
Ryan Stewart
1
Sí, pero mi comentario es válido en el contexto de lo que OP preguntó en el comentario posterior que no sabía.
Shahzeb
18

Las versiones más recientes del proveedor de JPA hibernate aplican las restricciones de validación de bean (JSR 303) como @NotNullDDL de forma predeterminada (gracias a los hibernate.validator.apply_to_ddl propertyvalores predeterminados de true). Pero no hay garantía de que otros proveedores de JPA tengan o incluso tengan la capacidad de hacerlo.

Debe usar anotaciones de validación de bean @NotNullpara asegurarse de que las propiedades de bean se establezcan en un valor no nulo, al validar java beans en la JVM (esto no tiene nada que ver con las restricciones de la base de datos, pero en la mayoría de las situaciones debería corresponderles).

Además, debe usar la anotación JPA @Column(nullable = false)para dar al proveedor de jpa sugerencias para generar el DDL correcto para crear columnas de tabla con las restricciones de la base de datos que desee. Si puede o quiere confiar en un proveedor de JPA como Hibernate, que aplica las restricciones de validación de bean a DDL de forma predeterminada, puede omitirlas.

Sebastian Theek
fuente
10

Es interesante notar que todas las fuentes enfatizan que @Column (nullable = false) se usa solo para la generación de DDL.

Sin embargo, incluso si no hay una anotación @NotNull, y la opción hibernate.check_nullability está establecida en true, Hibernate realizará la validación de las entidades para que persistan.

Lanzará PropertyValueException diciendo que "la propiedad no nula hace referencia a un valor nulo o transitorio", si nullable = los atributos falsos no tienen valores, incluso si tales restricciones no se implementan en la capa de la base de datos.

Más información sobre la opción hibernate.check_nullability está disponible aquí: http://docs.jboss.org/hibernate/orm/5.0/userguide/html_single/Hibernate_User_Guide.html#configurations-mapping .

Aleksandar Radulović
fuente
7

La @Columnanotación JPA

El nullableatributo de la @Columnanotación tiene dos propósitos:

  • es usado por la herramienta de generación de esquemas
  • Hibernate lo utiliza durante el vaciado del contexto de persistencia

Herramienta de generación de esquemas

La herramienta de generación de esquemas HBM2DDL traduce el @Column(nullable = false)atributo de entidad a una NOT NULLrestricción para la columna de la tabla asociada al generar la CREATE TABLEdeclaración.

Como expliqué en la Guía del usuario de Hibernate , es mejor usar una herramienta como Flyway en lugar de confiar en el mecanismo HBM2DDL para generar el esquema de la base de datos.

Persistencia de la descarga del contexto

Al vaciar el contexto de persistencia, Hibernate ORM también usa el @Column(nullable = false)atributo de entidad:

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

Si la validación falla, Hibernate arrojará un PropertyValueException, e impide que la instrucción INSERT o UPDATE se ejecute de forma necesaria:

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

Para obtener más detalles sobre cómo funciona el mecanismo de descarga Hibernate, consulte este artículo .

La @NotNullanotación de validación de frijoles

La @NotNullanotación está definida por Bean Validation y, al igual que Hibernate ORM es la implementación de JPA más popular, la implementación de Bean Validation más popular es el marco de Hibernate Validator .

Al usar Hibernate Validator junto con Hibernate ORM, Hibernate Validator arrojará un ConstraintViolationmensaje al validar la entidad.

Vlad Mihalcea
fuente
¿Por qué afirma que la ruta de vuelo es mejor que generar un esquema?
Andronicus
1
Esa es una buena observación. Actualicé la respuesta con un enlace de referencia.
Vlad Mihalcea
Gracias por la referencia y gran respuesta!
Andronicus