简体   繁体   English

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

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

I have the follwoing entity:我有以下实体:

@Entity
public class A {

  // id, etc..

  @OneToOne
  private B b;
}

The table a already exists and when i add the new field b to it, hibernate executes the following:a已经存在,当我向其中添加新字段b时,hibernate 执行以下操作:

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

As you see, the foreign key column b_id is not unique.如您所见,外键列b_id不是唯一的。 Why is that the case?为什么会这样? Doesn´t the One-to-One relation imply that the foreign key has to be unique?一对一关系不是意味着外键必须是唯一的吗? That´s also what i found in the JPA specification for unidirectional One-to-One relatoins:这也是我在单向一对一关系的 JPA 规范中发现的内容:

[...] The foreign key column has the same type as the primary key of table B and there is a unique key constraint on it. [...] 外键列与表 B 的主键类型相同,并且有一个唯一键约束。

To make it work i have to explicitally add the @JoinColumn(unique=true) annotation to the field.为了使它工作,我必须显式地将@JoinColumn(unique=true)注释添加到字段中。 Why do i have to do that explicitally?为什么我必须明确地这样做?

Bi-directional @OneToOne双向@OneToOne

In order to create a unique constraint you have to create a complete bi-directional OneToOne relation.为了创建唯一约束,您必须创建一个完整的双向OneToOne关系。

This means you have to add @OneToOne annotation on the Parent ( Owning ) entity, and add @OneToOne(mappedBy="...") on the Child entity.这意味着您必须在Parent ( Owning ) 实体上添加@OneToOne注释,并在Child实体上添加@OneToOne(mappedBy="...")

This will create a unique constraint on your id column.这将在您的id列上创建一个唯一约束。

Otherwise, you're modeling two different relations instead of one bi-directional relation;否则,您正在建模两种不同的关系,而不是一种双向关系; because of that nothing is stopping the current model from having two Childs pointing to the same Parent.因为没有什么能阻止当前模型让两个孩子指向同一个父级。

The official JavaDoc for @OneToOne annotation has more information on additional parameters and advice on bi-directional relation. @OneToOne 注释的官方JavaDoc有更多关于附加参数和双向关系建议的信息。

UPD: Link to hibernate specification on how it is handling of @OneToOne relation: UPD: 链接到有关如何处理@OneToOne关系的休眠规范

  1. When using a bidirectional @OneToOne association, Hibernate enforces the unique constraint upon fetching the child-side.当使用双向@OneToOne关联时,Hibernate 在获取子端时强制执行唯一约束。
  2. A unidirectional association follows the relational database foreign key semantics, the client-side owning the relationship.单向关联遵循关系数据库外键语义,客户端拥有关系。

In your case在你的情况下

This means that on your B entity model you should add a field with your A entity and annotate it with @OneToOne(mappedBy="b") to make your relation bi-direactional and complete, restricting access to single Parent and creating a unique constraint.这意味着在您的B实体模型上,您应该为A实体添加一个字段,并使用@OneToOne(mappedBy="b")对其进行注释,以使您的关系双向且完整,限制对单个 Parent 的访问并创建唯一约束.

I came across this issue recently.我最近遇到了这个问题。 My assumptions were @OneToOne must add a unique constraint on the foreign key.我的假设是@OneToOne必须在外键上添加唯一约束。 But hibernate doesn't do that.但是休眠不会这样做。

See this section in the hibernate docs.请参阅 hibernate 文档中的这一部分 Neither unidirectional nor bidirectional mappings add unique constraint (evident from the queries in the docs).单向映射和双向映射都没有添加唯一约束(从文档中的查询中可以看出)。 That means hibernate won't throw an exception when adding rows with same foreign keys.这意味着在添加具有相同外键的行时,hibernate 不会抛出异常。

Although note that in case of bidirectional mapping, hibernate does a uniqueness check when fetching the parent entity (but not child).尽管请注意,在双向映射的情况下,hibernate 在获取父实体(但不是子实体)时会进行唯一性检查 If there are multiple child ( owning ) entities refering to the same parent entity which is being fetched, hibernate throws a org.hibernate.exception.ConstraintViolationException .如果有多个子(拥有)实体引用正在获取的同一个父实体,hibernate 会抛出org.hibernate.exception.ConstraintViolationException

The solution is to add @JoinColumn(unique = true, ...) on your child.解决方案是在您的孩子上添加@JoinColumn(unique = true, ...) This will also throws an error when inserting a row with a non-unique foreign key in the table.在表中插入具有非唯一外键的行时,这也会引发错误。

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

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