困惑:使用JPA和Hibernate的@NotNull与@Column(nullable = false)


242
  1. 当它们出现在的字段/获取器上时,它们@Entity之间有什么区别?(我通过Hibernate保留了Entity )。

  2. 它们每个都属于什么框架和/或规范?

  3. @NotNull位于中javax.validation.constraints。在javax.validation.constraints.NotNulljavadoc中说

    带注释的元素不能为空

    但是它没有提到数据库中元素的表示形式,那么为什么nullable=false要在列中添加约束呢?

Answers:


328

@NotNullJSR 303 Bean验证批注。它与数据库约束本身无关。由于Hibernate是JSR 303的参考实现,因此它会智能地选择这些约束并将它们转换为数据库约束,因此您只需花1英镑即可获得2个。@Column(nullable = false)是JPA声明列为非空的方式。即,前者用于验证,而后者则用于指示数据库架构详细信息。您将从Hibernate的验证批注中获得一些额外的(欢迎使用!)帮助。


2
谢谢!因此,如果我不想将JPA持久性与Hibernate实现联系在一起(即更改为EJB3),那么我必须同时使用两个注释(在字段及其列中均禁止为null)?
全神贯注的

3
我不知道。没有说明JPA提供程序必须识别JSR 303批注的规范,但这并不意味着其他提供程序不能识别。我不能说有没有。
瑞安·斯图尔特

7
JPA提供程序不需要提供JSR303实现,但是根据提供与任何第三方JSR303实现集成的能力所需的规范。因此,虽然Hibernate确实提供了JSR303,但您可能出于任何原因决定不使用他们的JSR303,或者与其他人一起去使用,或者使用像openJPA这样的JPA实现并使用其他人来提供JSR303。还要注意,Hibernate的JPA实现也是EJB3。 “如果我不想让JPA持久性与Hibernate实现联系在一起(即更改为EJB3),则JPA是EJB3规范的一部分。
2011年

5
@Shahzeb:问题不在于谁支持/提供JSR 303验证。这是关于哪些ORM(S)承认JSR 303个注解一样@NotNull@Size@Min@Max,等,并翻译成那些数据库约束。
瑞安·斯图尔特

1
是的,但是我的评论在您不知道的后续评论中OP所要求的范围内是有效的。
2011年

18

休眠的JPA提供程序的最新版本@NotNull默认将Bean验证约束(JSR 303)应用于DDL(由于hibernate.validator.apply_to_ddl property默认为true)。但是,不能保证其他JPA提供程序也可以做到这一点。

@NotNull在验证JVM中的Java bean时,应使用bean验证批注来确保将bean属性设置为非空值(这与数据库约束无关,但在大多数情况下应与它们对应)。

您还应该使用JPA批注,例如@Column(nullable = false)给jpa提供者提示以生成正确的DDL,以创建具有所需数据库约束的表列。如果您可以或希望依靠像Hibernate这样的JPA提供程序,该提供程序默认将Bean验证约束应用于DDL,则可以忽略它们。


10

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

但是,即使没有@NotNull批注,并且hibernate.check_nullability选项设置为true,Hibernate也会对要保留的实体执行验证。

如果nullable = false属性没有值,即使没有在数据库层实现这种限制,也会抛出PropertyValueException,指出“非null属性引用了null或瞬态值”。

有关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的用户指南,它更好地使用工具,如迁飞,而不是依靠就是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]
        );    
}

有关Hibernate刷新机制如何工作的更多详细信息,请参阅本文

Bean验证@NotNull注释

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

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


为什么说状态比生成模式好?
Andronicus

1
这是一个很好的观察。我用参考链接更新了答案。
弗拉德·米哈尔恰

感谢您的参考和好评!
Andronicus
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.