保存secondary Entity时如何持久化oneToOne关系



我正在使用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", allocationSize = 1, 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。settentityb:

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);

最新更新