问题描述
我正在使用 SPRING DATA JPA 并且我有以下实体:
public class EntityA {
@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE,generator = "SOME_SEQ")
@SequenceGenerator(sequenceName = "SOME_SEQ",allocationSize = 1,name = "SOME_SEQ")
private Long id;
private String name;
@OnetoOne(mappedBy = "entityBField",cascade = CascadeType.ALL)
private EntityB entityB;
}
public class EntityB {
@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE,generator = "SOME_OTHER_SEQ")
@SequenceGenerator(sequenceName = "SOME_OTHER_SEQ",name = "SOME_OTHER_SEQ")
private Long id;
private Integer type;
@OnetoOne
@JoinColumn(name = "entityaId",referencedColumnName = "id")
private EntityA entityBField;
}
这是表定义:
create table EntityA(
id int primary key,name varchar(255)
);
create table EntityB(
id int primary key,type int,entitya_Id int FOREIGN KEY ("entitya_Id")
REFERENCES "EntityA" ("id")
);
我创建并保存一个实例如下:
EntityA a = new EntityA();
EntityB b = new EntityB();
a.setEntityB(b);
entityARepository.save(a)
发生的情况是entityA 和entityB 都被持久化了,但EntityB 上的外键entityaId 为空。 您能否建议我应该如何保留将 EntityB 链接到 EntityA 的外键?
解决方法
你需要像这样实现方法EntityA.setEntityB:
public class EntityA {
public void setEntityB(EntityB entityB) {
if (entityB == null) {
if (this.entityB != null) {
this.entityB.setEntityBField(null);
}
}
else {
entityB.setEntityBField(this);
}
this.entityB = entityB;
}
}
EntityB.setEntityBField 应该是通常的 setter:
public class EntityB {
public void setEntityBField(EntityA entityBField) {
this.entityBField = entityBField;
}
}
此外,您可能需要在注释中使用“optional = false”:
@OneToOne(mappedBy = "entityBField",cascade = CascadeType.ALL,optional = false)
private EntityB entityB;
请参阅本文中的示例: https://vladmihalcea.com/the-best-way-to-map-a-onetoone-relationship-with-jpa-and-hibernate/
注意:
mappedBy = "entityBField"
表示
EntityB.entityBField
负责管理一对一关系,
因此,当您创建 EntityB b = new EntityB()
并设置 a.setEntityB(b)
时,则在执行级联保存时 b.entityBField
为空:entityARepository.save(a)
这就是数据库中 b.entityBField
(外键“entitya_Id”)为空的原因。
通过在 EntityA 中实现正确的 setter,您可以帮助 JPA 理解,entityB.entityBField
应该设置为 EntityA 的主键 (entityB.setEntityBField(this)
)
最简单的解决方案是这样的:
EntityA a = new EntityA();
EntityB b = new EntityB();
b.setEntityBField(a);
entityARepository.save(a)
您需要进行的唯一更改是以下行:
b.setEntityBField(a);