保存辅助实体时如何保持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",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);

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...