混淆:@NotNull vs. @Column(nullable = false)与JPA和Hibernate

  1. 当它们出现在@Entity的字段/getter上时,它们之间有什么区别?(我通过Hibernate持久化实体)。

  2. 它们各自属于什么框架和/或规范?

  3. @NotNull位于javax.validation.constraints中。在javax.validation.constraints.NotNull javadoc中,它说

    带注释的元素不能为空

    但它并没有谈到元素在数据库中的表示,所以为什么我要将约束nullable=false添加到列中?< / p >

174318 次浏览

@NotNull是一个JSR 303 Bean验证注释。它与数据库约束本身无关。但是,由于Hibernate是JSR 303的参考实现,因此它可以智能地获取这些约束并将它们转换为数据库约束,因此您可以以一价买二。@Column(nullable = false)是JPA声明一个列为非空的方式。也就是说,前者用于验证,后者用于指示数据库模式细节。您只是从Hibernate获得了一些关于验证注释的额外帮助(欢迎!)。

hibernate JPA提供者的最新版本在默认情况下将bean验证约束(JSR 303)如@NotNull应用到DDL(由于hibernate.validator.apply_to_ddl property默认为true)。但是,并不能保证其他JPA提供者会这样做,甚至有能力这样做。

当在JVM中验证java bean时,您应该使用诸如@NotNull这样的bean验证注释来确保bean属性被设置为一个非空值(这与数据库约束无关,但在大多数情况下应该对应于它们)。

您还应该使用诸如@Column(nullable = false)之类的JPA注释来给JPA提供者提示,以生成正确的DDL,用于创建带有所需数据库约束的表列。如果您能够或希望依赖于像Hibernate这样的JPA提供者,它在默认情况下将bean验证约束应用到DDL,那么您可以省略它们。

有趣的是,所有来源都强调@Column(nullable=false)仅用于DDL生成。

但是,即使没有@NotNull注释,也会休眠。check_nullability选项设置为true时,Hibernate将对要持久化的实体执行验证。

如果nullable=false属性没有值,即使在数据库层没有实现这样的限制,它也会抛出PropertyValueException,表示“not-null属性引用了一个空值或瞬态值”。

更多关于hibernate的信息。check_nullability选项在这里可用:http://docs.jboss.org/hibernate/orm/5.0/userguide/html_single/Hibernate_User_Guide.html#configurations-mapping

JPA @Column注释

@Column注释的nullable属性有两个用途:

  • 模式生成工具使用它
  • Hibernate在刷新持久性上下文期间使用它

架构生成工具

在生成CREATE TABLE语句时,HBM2DDL模式生成工具将@Column(nullable = false)实体属性转换为关联表列的NOT NULL约束。

正如我在Hibernate用户指南中解释的那样,最好使用像再经这样的工具来生成数据库模式,而不是依赖于HBM2DDL机制。

持久性上下文刷新

当刷新持久性上下文时,Hibernate ORM也使用@Column(nullable = false)实体属性:

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

如果验证失败,Hibernate将抛出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]
);
}

Bean验证@NotNull注释

@NotNull注释是由Bean验证定义的,就像Hibernate ORM是最流行的JPA实现一样,最流行的Bean验证实现是Hibernate验证器框架。

当Hibernate Validator与Hibernate ORM一起使用时,Hibernate Validator在验证实体时将抛出ConstraintViolation