jpa 现有实体在更新父实体后会丢失父实体

oyt4ldly  于 2023-03-23  发布在  其他
关注(0)|答案(1)|浏览(148)

以下是Sping Boot 应用程序中具有一对一和一对多关系的实体类的父结构:

@Entity
@SuppressWarnings("common-java:DuplicatedBlocks")
public class A implements Serializable {

  private static final long serialVersionUID = 1L;
   @Id
  @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "sequenceGenerator")
  @SequenceGenerator(name = "sequenceGenerator")
  @Column(name = "id")
  private Long id;

  @Column(name = "name")
  private String name;

  @JsonIgnoreProperties(value = { "a" }, allowSetters = true)
  @OneToOne(mappedBy = "a", cascade = CascadeType.ALL)
  private B b;

  @OneToMany(mappedBy = "a", cascade = CascadeType.ALL)
  @JsonIgnoreProperties(value = { "a" }, allowSetters = true)
  private List<C> cs = new ArrayList<>();

   ...
}

@Entity
@SuppressWarnings("common-java:DuplicatedBlocks")
public class b implements Serializable {

  private static final long serialVersionUID = 1L;

  @Id
  @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "sequenceGenerator")
  @SequenceGenerator(name = "sequenceGenerator")
  @Column(name = "id")
  private Long id;

  @JsonIgnoreProperties(
    value = { "b", "cs", ... },
    allowSetters = true
)
    @OneToOne
    @JoinColumn(unique = true)
    private A a;
 // ..
}

@Entity
@SuppressWarnings("common-java:DuplicatedBlocks")
public class C implements Serializable {

  private static final long serialVersionUID = 1L;

  @Id
  @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "sequenceGenerator")
  @SequenceGenerator(name = "sequenceGenerator")
  @Column(name = "id")
  private Long id;

  @ManyToOne
  @JsonIgnoreProperties(
    value = { "b", "cs", ...},
    allowSetters = true
)
  private A a;

 // ...
}

我使用aRepository.save(a)来保存实体A的一个新示例。它非常出色,因为一个save方法调用就可以处理其子实体的所有数据阻力。
在更新实体数据集时,一对多关系会出现问题。

A oldA = ... ; // from the DB
A newA = ...; // new data
newA.setId(oldA.getId);
B newB = ...;
newB.setA(newA);
newB.setId(oldB.getId());
newA.setB(newB);

List<C> cList = ...; // new data
newA.setCs(cList);

aRepository.save(newA);

除了实体C的数据外,其他数据都可以正常工作。实体B被更新。新的实体C数据也被插入到DB表中。但是,现有的实体C数据失去了其父项。这些数据的父列变为空。这种类型的更新的正确方法是什么?我应该通过使用每个实体的存储库来执行这种类型的更新吗?

46scxncf

46scxncf1#

这是一个双向的关系,你只设置了一方(A的C列表),C对As的引用为空/null。由于双方都不同步,JPA将使用拥有方来确定要放入数据库的内容。在这种情况下,你将A中的所有内容Map为另一方拥有的内容。
您的A-B关系正在设置,因为您正在设置双方:

newB.setA(newA);
newA.setB(newB);

如果你想这样做,你需要以同样的方式设置C对A的引用:

newA.setCs(cList);
cList.stream().forEach( c -> c.setA(newA) );

相关问题