[英]foreign key constraint in One To One relationship in JPA hibernate
我有两个实体A
和B
,一对一的关系。 当我想将它们插入数据库时,我收到以下错误:
不能添加或更新子行,外键约束失败(
mydb
。a
,约束FK_77pkrkrin5nqsx16b6nw6k9r7
外键(id
)参考b
(b_id
))
@JsonInclude(JsonInclude.Include.NON_NULL)
@JsonIgnoreProperties(ignoreUnknown = true, value={"hibernateLazyInitializer", "handler"})
@Generated("org.jsonschema2pojo")
@Inheritance(strategy = InheritanceType.JOINED)
@Entity
public class A {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@JsonIgnore
private Integer id;
@OneToOne(cascade = CascadeType.ALL, fetch = FetchType.LAZY, optional = false)
@PrimaryKeyJoinColumn(referencedColumnName="AId")
@JsonIgnore
private B b;
}
@JsonInclude(JsonInclude.Include.NON_NULL)
@JsonIgnoreProperties(ignoreUnknown = true, value = {"hibernateLazyInitializer", "handler"})
@Generated("org.jsonschema2pojo")
@Entity
public class B {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private int bId;
@OneToOne()
@JsonIgnore
private A a;
}
如果我删除optional=false
,插入操作将完美地工作。 在将对象插入DB之前检查了对象,并确保A
包含B
, B
包含A
A
和B
创建的SQL脚本是:
Hibernate:创建表b(b_id整数不为null auto_increment,string_results longtext,a_id整数,主键(b_id))
Hibernate:创建表a(id整数不为null auto_increment,主键(id))
Hibernate:alter table b添加约束FK_o3oen721etlltdc7ls82524nh外键(detail_id)引用一个(id)
Hibernate:alter table a add constraint FK_77pkrkrin5nqsx16b6nw6k9r7 foreign key(id)references b(b_id)
当我看到以下句子时:
我在将对象插入DB之前检查了对象,并确保A包含B和B包含A.
我想你想创建一个双向的一对一关系。 如果是这样,您当前的映射无法按预期工作。 让我们看看JPA 2.0规范 (下载链接)对此有何了解:
关系可以是双向的或单向的。 双向关系具有拥有方和反向(非拥有方)。 单向关系只有一个拥有方。 关系的拥有方确定数据库中关系的更新,如3.2.4节所述。
以下规则适用于双向关系:
•双向关系的反面必须通过使用OneToOne,OneToMany或ManyToMany批注的mappedBy元素来引用其拥有方。 mappedBy元素指定作为关系所有者的实体中的属性或字段。
•一对多/多对一双向关系的多方必须是拥有方,因此无法在ManyToOne批注上指定mappedBy元素。
•对于一对一双向关系,拥有方对应于包含相应外键的一侧。
•对于多对多双向关系,任何一方都可能是拥有方。
因此,根据规范,双向一对一关系中的一个实体必须成为拥有方,而另一个实体必须是反方。 假设实体A
是拥有方,以下映射应该起作用:
@Entity
public class A {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Integer id;
@OneToOne(cascade = CascadeType.ALL, fetch = FetchType.LAZY, optional = false)
@JoinColumn(name="b_id", referencedColumnName="ID")
private B b;
}
@Entity
public class B {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private int id;
@OneToOne(mappedBy = "b")
private A a;
}
为了使上述映射工作或者必须自动生成物理表,或者如果您想自己创建表,相应的SQL应该如下所示:
create table a (id integer not null auto_increment,
b_id integer not null,
primary key (id),
foreign key b_id references b (id));
create table b (id integer not null auto_increment,
string_results longtext,
primary key (id));
注意:
我删除了特定于JSON的注释以使代码更短(我对它们没有任何了解)
如果要将实体B
作为拥有方,则必须相应地调整关系映射。
@JoinColumn
注释总是在自己的方面。
由于时间不够,我还没有测试过代码。 如果您发现任何错误(尤其是MySQL语法),请给我留言。
来自hibernate的文档:
(可选)关联是否可选。 如果设置为false,则必须始终存在非空关系。
在创建B时,b_id不可用,它是在数据库发生刷新时创建的。
由于A在B(b_id)上具有外键关系,因此在插入A或将此外键关系标记为可选之前,需要创建B及其id。
创建B并将其刷新到数据库,然后创建A. B不需要A作为其A定义B的外键而不反之亦然,B对A的引用只是反身,双向外键将创建循环参考问题。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.