首页 文章

Spring Data JPA Repository with Hibernate - persist(sql insert)父实体,但只更新嵌套的子实体

提问于
浏览
1

我正在使用Spring数据,JPA,Hibernate组合开发Spring Boot应用程序 . 下面是我正在努力解决的问题,即在将父实体作为新插入父实体时,预期行为仅更新某些子实体 .

实体类

@Entity
public class A {
  @Id
  private long id;

  @ManyToOne
  @JoinColumn (name = "B_ID")
  @Cascade ( { CascadeType.ALL } )
  private B b;
}

@Entity
@DynamicUpdate
public class B {
  @Id
  private long id;

  @OneToMany (mappedBy = "b")
  @Cascade ( { CascadeType.ALL } )
  private Set<A> as;

  @ManyToOne
  @JoinColumn (name = "C_ID")
  @Cascade ( { CascadeType.ALL } )
  private C c;
}


@Entity
@DynamicUpdate
public class C {
  @Id
  private long id;

  @OneToMany (mappedBy = "c")
  @Cascade ( { CascadeType.ALL } )
  private Set<B> bs;

  @ManyToOne
  @JoinColumn (name = "D_ID")
  @Cascade ( { CascadeType.ALL } )
  private D d;

  @ManyToOne
  @JoinColumn (name = "E_ID")
  @Cascade ( { CascadeType.ALL } )
  private E e;
}


@Entity
@DynamicUpdate
public class D {
  @Id
  private long id;

  @OneToMany (mappedBy = "d")
  @Cascade ( { CascadeType.ALL } )
  private Set<C> cs;
}

@Entity
@DynamicUpdate
public class E {
  @Id
  private long id;

  @OneToMany (mappedBy = "e")
  @Cascade ( { CascadeType.ALL } )
  private Set<C> cs;
}

以下是我在应用中执行的步骤:

  • 从回购中拉出 B ;如果存在,则更新其某些字段值[或]使用字段值创建新的 B .

  • 创建 A 的新实例并将 B 设置为 A .

  • 持续 A (通过调用 JpaCrudRepository.save(A) ) .

成功部分:当repo中不存在 B 时,一切正常 . 意思是:

  • 创建了 B (和 CDE )的新实例,

  • 这个新创建的 B 被设置为 A

  • 并且 A 被持久保存成功(在DB / repo中的所有相应表中插入新行) .

失败部分:

  • 现在,当repo中已经存在 B 时,现有的 B 被正确拉出,

  • B 的某些字段已更新,而 CDE 未被触及,

  • 此更新的 B 设置为 A .

  • 但是当试图保持 A 时,现在会在 DE 上抛出唯一约束违规 .

所有实体都标有以下内容:

• ID as auto-generated column (used as PK implicitly),
• Mapping between entities using the ID column,
• CascadeType ALL wherever mappings like OneToMany, ManyToOne are applied,
• Dynamic update annotation.

到目前为止,我可以通过网络收集有关此主题的内容:

JPA Repository没有't have merge() or update() operations available explicitly, and the save() is supposed to cover those. And this save() operation works by calling merge() if the entity instance exists already Or by calling persist() if it is new. And digging further, the entity'的ID列用于确定它在repo中的存在 . 如果此ID为null,则将entity确定为new,如果ID不为null,则将其确定为现有ID .

因此,在我上面的失败案例中,当从repo中提取现有的 B 实体实例时,它已经具有非空ID .

所以我现在还不清楚我在这里错过了什么 . 我尝试在网上找到任何匹配的解决方案,但尚未到达 .

有人可以帮我确定我的方法有什么问题吗?

1 回答

  • 0

    找到了问题和解决方案 . 由于A和B被创建为新的,随后C,D,E都被创建为新的,导致违规 . 因此,为了解决这个问题,我必须从DB中提取C,D和E中的每个现有实体,并在尝试持久化之前分别/分层地在新创建的B实体内设置它们 .

    基本上,如果实体嵌套在即将保留的父实体中,则不要为该实体创建新实例 . 目标是在类似记录已存在时更新 .

相关问题