Hibernate @OneToMany & @OneToOne 关联到不可为空的实体

Posted

技术标签:

【中文标题】Hibernate @OneToMany & @OneToOne 关联到不可为空的实体【英文标题】:Hibernate @OneToMany & @OneToOne associations to non-nullable entity 【发布时间】:2022-01-08 22:14:18 【问题描述】:

我有以下问题。我想建模一个UserProfile,它可能有多个UserEmails。其中一封电子邮件是个人资料的主要电子邮件,我想强制必须有一个主要电子邮件(不是null)。

我已经设置了这样的实体:

@Entity
@Table(name = "user_profile")
public class UserProfile 
    
   @NotNull
   @OneToOne
   @JoinColumn(name = "primary_user_email_id", nullable = false)
   private UserEmail primaryEmail;

   @OneToMany(cascade = CascadeType.ALL, mappedBy = "userProfile", orphanRemoval = true)
   private List<UserEmail> emails;

   // other fields for profile details e.g. username, id ...

@Entity
@Table(name = "user_email")
public class UserEmail 
    
   @ManyToOne
   @JoinColumn(name = "user_profile_id", nullable = false)
   private UserProfile userProfile;

   // other fields for email details e.g. address, isConfirmed, id ...

我在数据库列 user_profile.primary_user_email_iduser_email.user_profile_id 上没有 -nullable 约束以及外键约束。

如果我从primary_user_email_id 列中删除not-nullable 约束(连同@NotNull 注释和@JoinColumnnullable 属性),此设置工作正常。所以我可以创建新的UserProfiles 并将新的UserEmails 添加到emails 的列表中并保留配置文件。之后,我可以将其中一封电子邮件设置为主电子邮件并更新个人资料。

但是,我想保留数据库约束,这样我就可以强制要求必须有一个主电子邮件。我认为这可能是不可能的,因为如果我尝试一次保存所有内容(新的配置文件和新的主电子邮件也在电子邮件列表中),总是会出现错误,即由于瞬态而违反了非nullable 约束实体。

有没有办法为primaryEmail 强制设置一个不可为空的列?也许有更好的方法来建模这个用例?

【问题讨论】:

【参考方案1】:

至少某些数据库(如 Postgres 或 Oracle)支持此用例的延迟约束。它们直到提交时间才强制执行,因此您可以准备两行并将它们一起提交。

【讨论】:

谢谢,我不知道。不幸的是,我想支持 mysql,但 MySQL 似乎不支持可延迟约束。

以上是关于Hibernate @OneToMany & @OneToOne 关联到不可为空的实体的主要内容,如果未能解决你的问题,请参考以下文章

Hibernate 从 onetomany 中删除

Hibernate - OneToMany 单向映射 - SQLGrammarException

Hibernate @OneToMany 的意外行为

在 Hibernate/JPA 中保存一个带有子对象的对象 - @OneToMany

Hibernate @OneToMany 错误:键 'PRIMARY' 的重复条目 '0'

Hibernate如何正确删除@OneToMany中的孩子?