[英]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
关系。
这意味着您必须在Parent ( Owning ) 实体上添加@OneToOne
注释,并在Child实体上添加@OneToOne(mappedBy="...")
。
这将在您的id列上创建一个唯一约束。
否则,您正在建模两种不同的关系,而不是一种双向关系; 因为没有什么能阻止当前模型让两个孩子指向同一个父级。
@OneToOne 注释的官方JavaDoc有更多关于附加参数和双向关系建议的信息。
UPD: 链接到有关如何处理@OneToOne
关系的休眠规范:
这意味着在您的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.