繁体   English   中英

JPA 一对一关系创建非唯一外键

[英]JPA One-to-One relation creates a non unique foreign key

我有以下实体:

@Entity
public class A {

  // id, etc..

  @OneToOne
  private B b;
}

a已经存在,当我向其中添加新字段b时,hibernate 执行以下操作:

alter table a add column b_id int8
alter table a add constraint FKg76mxqt8whi8t8p4i7el95910 foreign key (b_id) references b

如您所见,外键列b_id不是唯一的。 为什么会这样? 一对一关系不是意味着外键必须是唯一的吗? 这也是我在单向一对一关系的 JPA 规范中发现的内容:

[...] 外键列与表 B 的主键类型相同,并且有一个唯一键约束。

为了使它工作,我必须显式地将@JoinColumn(unique=true)注释添加到字段中。 为什么我必须明确地这样做?

双向@OneToOne

为了创建唯一约束,您必须创建一个完整的双向OneToOne关系。

这意味着您必须在Parent ( Owning ) 实体上添加@OneToOne注释,并在Child实体上添加@OneToOne(mappedBy="...")

这将在您的id列上创建一个唯一约束。

否则,您正在建模两种不同的关系,而不是一种双向关系; 因为没有什么能阻止当前模型让两个孩子指向同一个父级。

@OneToOne 注释的官方JavaDoc有更多关于附加参数和双向关系建议的信息。

UPD: 链接到有关如何处理@OneToOne关系的休眠规范

  1. 当使用双向@OneToOne关联时,Hibernate 在获取子端时强制执行唯一约束。
  2. 单向关联遵循关系数据库外键语义,客户端拥有关系。

在你的情况下

这意味着在您的B实体模型上,您应该为A实体添加一个字段,并使用@OneToOne(mappedBy="b")对其进行注释,以使您的关系双向且完整,限制对单个 Parent 的访问并创建唯一约束.

我最近遇到了这个问题。 我的假设是@OneToOne必须在外键上添加唯一约束。 但是休眠不会这样做。

请参阅 hibernate 文档中的这一部分 单向映射和双向映射都没有添加唯一约束(从文档中的查询中可以看出)。 这意味着在添加具有相同外键的行时,hibernate 不会抛出异常。

尽管请注意,在双向映射的情况下,hibernate 在获取父实体(但不是子实体)时会进行唯一性检查 如果有多个子(拥有)实体引用正在获取的同一个父实体,hibernate 会抛出org.hibernate.exception.ConstraintViolationException

解决方案是在您的孩子上添加@JoinColumn(unique = true, ...) 在表中插入具有非唯一外键的行时,这也会引发错误。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM