有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java为什么Hibernate会在更新期间将json中的空id传递给子实体时插入新记录

我有最新消息。波乔斯:我把它简化了

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和外键仅作为值。但insert语句的最后一行是成功的

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...

它应该是更新,更新,然后插入


共 (2) 个答案

  1. # 1 楼答案

    • 当反序列化序列化实体实例时,需要获取持久的
      实体实例,并使用 来自此分离实例的新值
    • Hibernate merge通过从传递的对象(或 来自
      的现有实体实例 检索持久性上下文,或从
      加载新实例 数据库);将字段从传递的对象复制到此
      例子返回新更新的实例。
      • 所以,如果id为null,则找不到对象的实例,所以merge将插入新的 记录并返回对象
  2. # 2 楼答案

    您用cascade = CascadeType.ALL声明了caseOutlineDetails。因此,当您更新CaseOutlineHeader时,hibernate将自动更新列表,并在需要时插入行。然后你做你的东西,然后再插入它