简体   繁体   中英

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

I have the ff. pojos: i make it short for simplicity

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;
}

And then my service: It's pretty straightforward if the passed json of COD contains id that is not null it will update COH along with the COD . else if i passed a null id of COD i will save as a new entry in 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;
  }

Passed json data in swagger:

{
  "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"
}

As you can see i passed a second data in COD which dont have an id property it will be saved. while the first one will be updated which contains an id.

Here is my repo:

    @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;
  }

But in my logger i dont know why it inserts a new record first with id and foreign key only as the value. But on the last line of insert statement is successful

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

It should just be update,update,then insert.

You declared caseOutlineDetails with cascade = CascadeType.ALL . So when you're updating a CaseOutlineHeader , hibernate will automatically update the list, inserting rows if needed. Then you're doing your stuff and insert it again.

  • when deserializing the serialized entity instance, need to get a persistent
    entity instance from a persistence context and update its fields with new values from this detached instance
  • Hibernate merge finds an entity instance by id taken from the passed object (either an existing entity instance from the
    persistence context is retrieved, or a new instance loaded from
    the database); copies fields from the passed object to this
    instance; returns newly updated instance.
    • so if id is null that does not finds instance of the object so merge inserts the new record and returns the object.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM