簡體   English   中英

如果在更新過程中我在json中將空ID傳遞給子實體,為什么Hibernate插入新記錄

[英]Why Hibernate inserts a new record if i passed an empty id in json to child entity during update

我有事。 pojos:我為簡單起見簡化了它

public class CaseOutlineHeader{

  @Id
  @GeneratedValue(generator = "COH_SequenceStyleGenerator")
  @Column(name = "outline_id")
  private Long id;

  @OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY)
  @JoinColumn(name = "outline_id", nullable = true, referencedColumnName = "outline_id",
      foreignKey = @ForeignKey(name = "FK_COH_REF_COD_01"))
  private List<CaseOutlineDetails> caseOutlineDetails;

}

public class CaseOutlineDetails{

  @Id
  @GeneratedValue(generator = "COD_SequenceStyleGenerator")
  @Column(name = "ID")
  private Long id;

  @ManyToOne(targetEntity = MaintCaseEvent.class)
  @JoinColumn(name = "EVENT_ID", nullable = false,
      foreignKey = @ForeignKey(name = "FK_COD_REF_CASE_EVENT"),
      referencedColumnName = "CASE_EVENT_ID")
  private MaintCaseEvent eventId;

 @Column(name = "outline_id")
  private Long outlineId;
}

然后是我的服務:如果傳遞的COD json包含不為null的id,這將非常簡單,它將與COD一起更新COH。 否則,如果我傳遞了COD的空ID,我將另存為COD中的新條目。

 @Override
  @Transactional
  public CaseOutlineHeader update(CaseOutlineHeader caseoutline) {

    LOG.info("SERVICE: Updating CaseOutlineHeader...{}", caseoutline);

    if (!CollectionUtils.isEmpty(caseoutline.getCaseOutlineDetails())) {
      caseoutline.getCaseOutlineDetails().forEach(cod -> {
        if (cod.getId() != null) {
          cod.setUpdatedBy(cod.getUpdatedBy());
          cod.setUpdatedDate(new Date());
          caseOutlineHeaderRepository.update(caseoutline);
        } else {
          cod.setOutlineId(caseoutline.getId());
          cod.setCreatedBy("dwade");
          caseOutlineDetailsRepository.save(cod);
        }

      });
    }
    return caseoutline;
  }

大張旗鼓地傳遞json數據:

{
  "id": 1,
  "caseOutlineDetails": [
  { 
    "eventId": { "id": 1 },
    "updatedBy": "kobe",
    "id" : 1,
    "outlineId" : 1
  },
  {
    "eventId": { "id": 2},
    "outlineId" : 1
    }

  ],
  "caseType": "string",
  "code": "updateC",
  "description": "updateD",
  "updatedBy": "kobe",
  "updatedDate": "2018-07-23T00:55:16.767Z"
}

如您所見,我在COD中傳遞了第二個沒有id屬性的數據,它將被保存。 而第一個將更新,其中包含一個ID。

這是我的倉庫:

    @Override
    public CaseOutlineHeader update(CaseOutlineHeader caseOutlineHeader) {
        em.merge(caseOutlineHeader);
        em.flush();
        return caseOutlineHeader;
    }

  @Override
  public CaseOutlineDetails save(CaseOutlineDetails caseOutlineDetails) {
    LOG.info("REPOSITORY : SAVE = " + caseOutlineDetails);
    em.persist(caseOutlineDetails);
    return caseOutlineDetails;
  }

但是在我的記錄器中,我不知道為什么它首先以id和外鍵作為值插入新記錄。 但是在插入語句的最后一行是成功的

Hibernate: insert into case_outline_details (access_level...
Hibernate: update case_outline_header set access_level=?...
Hibernate: update case_outline_details set access_level=?...
Hibernate: select seq_cod.nextval from dual
Hibernate: insert into case_outline_details (access_level...

它應該只是更新,更新然后插入。

您使用cascade = CascadeType.ALL聲明了caseOutlineDetails 因此,當您更新CaseOutlineHeader ,hibernate將自動更新列表,並在需要時插入行。 然后,您正在做您的工作,然后再次插入。

  • 反序列化序列化實體實例時,需要獲得持久性
    持久性上下文中的實體實例,並使用此分離的實例中的新值更新其字段
  • Hibernate合並通過從傳遞的對象中獲取的ID查找一個實體實例(從
    檢索持久性上下文,或從中加載新實例
    數據庫); 將字段從傳遞的對象復制到此
    實例 返回新更新的實例。
    • 因此,如果id為null,則找不到對象實例,因此merge插入新記錄並返回對象。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM