Java @Column 中 nullable=true 的休眠处理

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/23996149/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-14 09:37:11  来源:igfitidea点击:

Hibernate handling of nullable=true in @Column

javamysqlhibernatejpaorm

提问by Aditya

I am using Hibernate with Springs backed by a Mysql db.

我正在使用带有 Mysql 数据库支持的 Springs 的 Hibernate。

Here is the entity similar to the one i use to make an entry

这是类似于我用来输入的实体

@Entity
@Table(name = "my_table") {

    @Basic
    @Column(name = "my_string", nullable = false)
    private String myString;
}

The sql definition is

sql定义是

CREATE TABLE `my_table` (
 `my_string` varchar(200) DEFAULT NULL,
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

Though the table allows null values, the column myString is non-nullable as per the JPA annotation. This is leading to unpredictable behaviour.

尽管该表允许空值,但根据 JPA 注释,列 myString 不可为空。这会导致不可预测的行为。

Q: Is the non-nullable ALWAYS enforced at the entity level while making inserts? Or is there some case in which it may be ignored

问:在进行插入时,是否始终在实体级别强制执行不可为空?或者在某些情况下它可能会被忽略

My expectation was that all of the entries should have been rejected. But with this setup, many entries (>7000) have gone into the table. Only sometimes i get a DataIntegrityViolation exception from spring

我的期望是所有条目都应该被拒绝。但是通过这种设置,许多条目 (>7000) 已进入表中。只是有时我会从春季收到 DataIntegrityViolation 异常

org.springframework.dao.DataIntegrityViolationException: not-null property references a null or transient value: ...; nested exception is org.hibernate.PropertyValueException: not-null property references a null or transient value: ....
    at org.springframework.orm.hibernate3.SessionFactoryUtils.convertHibernateAccessException(SessionFactoryUtils.java:652)
    at org.springframework.orm.jpa.vendor.HibernateJpaDialect.translateExceptionIfPossible(HibernateJpaDialect.java:104)
    at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.translateExceptionIfPossible(AbstractEntityManagerFactoryBean.java:403)
    at org.springframework.dao.support.ChainedPersistenceExceptionTranslator.translateExceptionIfPossible(ChainedPersistenceExceptionTranslator.java:58) 
    ....  
    ....
Caused by: org.hibernate.PropertyValueException: not-null property references a null or transient value: ....
    at org.hibernate.engine.internal.Nullability.checkNullability(Nullability.java:103)
    ....

I understand that having separate signature in the entity and the table is a bad practice, But i'm trying to identify what causes this behaviour and any other loopholes that might have been left out due to it.

我知道在实体和表中使用单独的签名是一种不好的做法,但我试图确定导致这种行为的原因以及可能因此而被遗漏的任何其他漏洞。

Versions -
Mysql- 5.5
Hibernate - 4.0.0
Hibernate-jpa - 2.0
Spring-core- 3.1.0
Spring-jdbc- 3.1.2

回答by Vlad Mihalcea

People frequently confuse the @Column(nullable) and @NotNull annotations.

人们经常混淆@Column(nullable) 和 @NotNull 注释

The @Column(nullable)is meant for the generated DDL scripts. But you don't use Hibernate to generate your DDL, so you shouldn't rely on it at all. What you want is @NotNullwhich is a runtime validation trigger.

@Column(nullable)是为生成的DDL脚本。但是您不使用 Hibernate 来生成您的 DDL,因此您根本不应该依赖它。您想要的是@NotNull哪个是运行时验证触发器。

If you define the Hibernate Validator Annotation (or JPA 2.0 ones) you can get the DDL for those as well:

如果您定义了 Hibernate Validator Annotation(或 JPA 2.0 的),您也可以获得这些 DDL

Out of the box, Hibernate (as of version 3.5.x) will translate the constraints you have defined for your entities into mapping metadata. For example, if a property of your entity is annotated @NotNull, its columns will be declared as not null in the DDL schema generated by Hibernate.

开箱即用,Hibernate(从 3.5.x 版开始)会将您为实体定义的约束转换为映射元数据。例如,如果您的实体的一个属性被注解为@NotNull,那么它的列将在 Hibernate 生成的 DDL 模式中声明为非空。

And make sure you enable validation if you're using JPA with Hibernate.

如果您在 Hibernate 中使用 JPA,请确保启用验证。

If you are using JPA 2 and Hibernate Validator is in the classpath the JPA2 specification requires that Bean Validation gets enabled. The properties javax.persistence.validation.group.pre-persist, javax.persistence.validation.group.pre-update and javax.persistence.validation.group.pre-remove as described in Section 10.1.2, “Hibernate event-based validation” can in this case be configured in persistence.xml. persistence.xml also defines a node validation-mode which can be set to AUTO, CALLBACK, NONE. The default is AUTO.

如果您使用的是 JPA 2 并且 Hibernate Validator 在类路径中,则 JPA2 规范要求启用 Bean 验证。属性 javax.persistence.validation.group.pre-persist、javax.persistence.validation.group.pre-update 和 javax.persistence.validation.group.pre-remove 如第 10.1.2 节“Hibernate event-based在这种情况下,可以在persistence.xml 中配置validation”。persistence.xml 还定义了一个节点验证模式,可以设置为 AUTO、CALLBACK、NONE。默认值为自动。