为什么 Hibernate 不抱怨必须是 @NotNull 的 'null' 值?
Why isn't Hibernate complaining about 'null' value that must be @NotNull?
我的@Entity class UpcomingOffer
中有这个:
@Entity
public class UpcomingOffer {
@Id
@GeneratedValue(strategy=GenerationType.IDENTITY)
@Column(name="ID")
private Long id;
@NotNull // Must not be null!
@OneToOne
private Store store;
// ...
}
但出于某种原因,我能够在没有设置 Store
的情况下保存 StoreOffer
:
UpcomingOffer upcomingOffer = new UpcomingOffer();
DateTime date = new DateTime(upcomingOfferDto.getDate());
upcomingOffer.setDate(date);
upcomingOffer.setStore(null);
保存它不会导致异常:
Session session = getSessionFactory().getCurrentSession();
session.saveOrUpdate(upcomingOffer);
这会导致更新即将到来的报价的条目,并且不会与拥有该 UpcomingOffer
的 Store
相关联。
为什么 Hibernate 在使用 @NotNull
注释时不在此处抛出异常?
尝试将 hibernate-validator 添加到类路径中
如果使用 Maven,请将此添加到您的 POM:
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-validator</artifactId>
<version>4.3.0.Final</version>
</dependency>
如果 gradle 将此添加到 build.gradle
'org.hibernate:hibernate-validator:4.3.0.Final'
如果您没有使用依赖管理/构建工具,那么您将不得不手动下载 jar 并将其放在您的类路径中
另一个可能的问题,可能相关,也可能不相关,您的@OneToOne 应该与 Store 实体或 UpcomingOffer 实体上的 @JoinColumn 配对。如果您正在进行双向映射,其中之一也应该定义 mappedBy 属性 。如果您让 Hibernate 生成数据库,它也可能没有按预期生成它。
@NotNull 不是 JPA 注释,它是 JSR 303/349 注释(Bean 验证)。正如@greyfox 所建议的那样,如果您将 hibernate-validator 添加到类路径中,那么 hibernate 将为您进行验证,因为 hibernate-validator 是 Bean Validation 规范的实现。
但我认为,如果您不想在那里接受 null,那么合适的方法是使用正确的 JPA 注释将列标记为可为空
@Column(nullable = false)
请注意,根据您生成数据库 table 的方式,您还需要更新 SQL table 或不更新。如果您让 hibernate 为您生成 table,那么 hibernate 将为您将与注释字段关联的列标记为 NOT NULL。
请注意,您可以采用任何一种方式(将验证留给 hibernate-validator 或仅在数据库级别强制执行验证,或两者都执行)...但是在数据库级别强制执行约束似乎是合适的,因为允许 null 对你来说没有意义。
编辑#1:
啊,我忘了这是一个外键字段。所以,是的,使用 @OneToOne 注释作为 @greyfox 也建议可以解决问题。
我的@Entity class UpcomingOffer
中有这个:
@Entity
public class UpcomingOffer {
@Id
@GeneratedValue(strategy=GenerationType.IDENTITY)
@Column(name="ID")
private Long id;
@NotNull // Must not be null!
@OneToOne
private Store store;
// ...
}
但出于某种原因,我能够在没有设置 Store
的情况下保存 StoreOffer
:
UpcomingOffer upcomingOffer = new UpcomingOffer();
DateTime date = new DateTime(upcomingOfferDto.getDate());
upcomingOffer.setDate(date);
upcomingOffer.setStore(null);
保存它不会导致异常:
Session session = getSessionFactory().getCurrentSession();
session.saveOrUpdate(upcomingOffer);
这会导致更新即将到来的报价的条目,并且不会与拥有该 UpcomingOffer
的 Store
相关联。
为什么 Hibernate 在使用 @NotNull
注释时不在此处抛出异常?
尝试将 hibernate-validator 添加到类路径中
如果使用 Maven,请将此添加到您的 POM:
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-validator</artifactId>
<version>4.3.0.Final</version>
</dependency>
如果 gradle 将此添加到 build.gradle
'org.hibernate:hibernate-validator:4.3.0.Final'
如果您没有使用依赖管理/构建工具,那么您将不得不手动下载 jar 并将其放在您的类路径中
另一个可能的问题,可能相关,也可能不相关,您的@OneToOne 应该与 Store 实体或 UpcomingOffer 实体上的 @JoinColumn 配对。如果您正在进行双向映射,其中之一也应该定义 mappedBy 属性 。如果您让 Hibernate 生成数据库,它也可能没有按预期生成它。
@NotNull 不是 JPA 注释,它是 JSR 303/349 注释(Bean 验证)。正如@greyfox 所建议的那样,如果您将 hibernate-validator 添加到类路径中,那么 hibernate 将为您进行验证,因为 hibernate-validator 是 Bean Validation 规范的实现。
但我认为,如果您不想在那里接受 null,那么合适的方法是使用正确的 JPA 注释将列标记为可为空
@Column(nullable = false)
请注意,根据您生成数据库 table 的方式,您还需要更新 SQL table 或不更新。如果您让 hibernate 为您生成 table,那么 hibernate 将为您将与注释字段关联的列标记为 NOT NULL。
请注意,您可以采用任何一种方式(将验证留给 hibernate-validator 或仅在数据库级别强制执行验证,或两者都执行)...但是在数据库级别强制执行约束似乎是合适的,因为允许 null 对你来说没有意义。
编辑#1:
啊,我忘了这是一个外键字段。所以,是的,使用 @OneToOne 注释作为 @greyfox 也建议可以解决问题。