Путаница: @NotNull против @Column (nullable = false) с JPA и Hibernate

242
  1. Когда они появляются на поле / получателе @Entity, чем они отличаются? (Я сохраняю сущность через Hibernate ).

  2. К какой структуре и / или спецификации принадлежит каждый из них?

  3. @NotNullнаходится внутри javax.validation.constraints. вjavax.validation.constraints.NotNull javadoc написано

    Аннотированный элемент не должен быть нулевым

    но это не говорит о представлении элемента в базе данных, так зачем мне добавлять ограничение nullable=falseк столбцу?

восхищенный
источник

Ответы:

328

@NotNullявляется аннотацией JSR 303 Bean Validation Это не имеет ничего общего с ограничениями базы данных. Однако, поскольку Hibernate является эталонной реализацией JSR 303, он разумно распознает эти ограничения и преобразует их в ограничения базы данных, поэтому вы получаете два по цене одного. @Column(nullable = false)способ JPA для объявления столбца не равным NULL. Т.е. первый предназначен для проверки, а второй - для указания деталей схемы базы данных. Вы просто получаете дополнительную (и добро пожаловать!) Помощь от Hibernate в аннотациях проверки.

Райан Стюарт
источник
2
Спасибо! Так что, если я хочу, чтобы мое постоянство JPA не было привязано к реализации Hibernate (то есть изменилось на EJB3), тогда я должен использовать обе аннотации (чтобы запретить нулевое значение как в поле, так и в его столбце)?
рапт
3
Я не знаю. Нет спецификации, в которой говорится, что поставщик JPA должен распознавать аннотации JSR 303, но это не означает, что другие поставщики этого не делают. Я не могу сказать, делает ли кто-нибудь или нет.
Райан Стюарт
7
Поставщики JPA не обязаны предоставлять реализацию JSR303, но согласно спецификации необходимы для обеспечения возможности интеграции с любой реализацией JSR303 третьей стороны. Поэтому, хотя Hibernate предоставляет JSR303, вы можете по какой-либо причине принять решение не использовать их и пойти с кем-то другим или использовать реализацию JPA, например openJPA, и использовать кого-то еще для обеспечения JSR303. Также обратите внимание, что реализация JPA Hibernate также является EJB3.Не правильно говорить «если я хочу, чтобы мое постоянство JPA не было связано с реализацией Hibernate (то есть переход на EJB3)», JPA является частью спецификации EJB3.
Шахзеб
5
@Shahzeb: Вопрос не в том, кто поддерживает / обеспечивает проверку JSR 303. Речь идет о которых ОРМ (s) признать JSR 303 аннотаций , как @NotNull, @Size, @Min, @Maxи т.д., и переводить те в ограничениях базы данных.
Райан Стюарт
1
Да, но мой комментарий действителен в контексте того, что ОП спросил в последующем комментарии, которого вы не знали.
Шахзеб
18

В самых последних версиях провайдера JPA hibernate применяются ограничения проверки bean-компонентов (JSR 303), например @NotNull по умолчанию для DDL (благодаря hibernate.validator.apply_to_ddl propertyзначениям по умолчаниюtrue ). Но нет никакой гарантии, что другие провайдеры JPA сделают или даже смогут это сделать.

Вы должны использовать аннотации проверки бобов, такие как @NotNull чтобы гарантировать, что для свойств bean-компонентов задано непустое значение, при проверке Java-бинов в JVM (это не имеет ничего общего с ограничениями базы данных, но в большинстве ситуаций должно соответствовать им).

Вы должны дополнительно использовать аннотацию JPA, например, @Column(nullable = false)чтобы давать подсказки провайдеру jpa для создания правильного DDL для создания столбцов таблицы с необходимыми ограничениями базы данных. Если вы можете или хотите положиться на поставщика JPA, такого как Hibernate, который по умолчанию применяет ограничения проверки bean-компонентов к DDL, то вы можете их опустить.

Себастьян Тик
источник
10

Интересно отметить, что все источники подчеркивают, что @Column (nullable = false) используется только для генерации DDL.

Однако даже если аннотации @NotNull нет, а для параметра hibernate.check_nullability задано значение true, Hibernate выполнит проверку сущностей, которые необходимо сохранить.

Он вызовет PropertyValueException, сообщив, что «свойство not-null ссылается на нулевое или временное значение», если атрибуты nullable = false не имеют значений, даже если такие ограничения не реализованы на уровне базы данных.

Дополнительная информация о параметре hibernate.check_nullability доступна здесь: http://docs.jboss.org/hibernate/orm/5.0/userguide/html_single/Hibernate_User_Guide.html#configurations-mapping .

Александар Радулович
источник
7

JPA @ColumnАннотация

nullableАтрибут @Columnаннотации имеет две цели:

  • он используется инструментом генерации схемы
  • он используется Hibernate во время очистки контекста постоянства

Инструмент генерации схемы

Инструмент генерирования схемы HBM2DDL преобразует @Column(nullable = false)атрибут сущности в NOT NULLограничение для связанного столбца таблицы при генерации CREATE TABLEоператора.

Как я объяснил в Руководстве пользователя Hibernate , лучше использовать такой инструмент, как Flyway, а не полагаться на механизм HBM2DDL для генерации схемы базы данных.

Постоянство контекста Flush

При очистке контекста персистентности Hibernate ORM также использует @Column(nullable = false)атрибут сущности:

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

Если проверка завершится неудачно, Hibernate сгенерирует a PropertyValueExceptionи предотвратит выполнение инструкции INSERT или 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]
        );    
}

Подробнее о том, как работает механизм сброса Hibernate, читайте в этой статье .

@NotNullАннотация для проверки бобов

@NotNullАннотаций определяется Bean Validation и, так же , как Hibernate ORM является наиболее популярной реализацией JPA, наиболее популярной реализация Bean Validation является Hibernate Validator рамки.

При использовании Hibernate Validator вместе с Hibernate ORM Hibernate Validator будет выдавать ConstraintViolationпри проверке сущности.

Влад Михалча
источник
Почему вы утверждаете, что пролетный путь лучше, чем создание схемы?
Андроник
1
Это хорошее наблюдение. Я обновил ответ ссылочной ссылкой.
Влад Михалча
Спасибо за ссылку и отличный ответ!
Андроник