Hibernate Map ID automatically from field

2020-05-03 09:45发布

I have something similar to this:

@Entity
@Table(name = "claim", schema = "test")
public class Claim implements Serializable {

   @Id
   @GeneratedValue(strategy = GenerationType.AUTO)
   @Column(name = "idClaim", unique = true, nullable = false)
   private Integer idClaim;

   @OneToOne(mappedBy = "claim", cascade = CascadeType.ALL, fetch = FetchType.LAZY)
   @JsonManagedReference
   private ClaimReturnInfo claimReturnInfo;

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

   // Getters and setters
}


@Entity
@Table(name = "claim_returninfo", schema = "test")
public class ClaimReturnInfo implements Serializable {

   @Id
   @Column(name = "Claim_idClaim")
   private Integer id;

   @MapsId("Claim_idClaim")
   @OneToOne(fetch = FetchType.LAZY)
   @JoinColumn(name = "Claim_idClaim")
   @JsonBackReference
   private Claim claim;

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

   // Getters and setters
}

ClaimReturnInfo Id is not autogenerated because we want to propagate the Id from its parent (Claim). We are not able to do this automatically and we are getting this error: ids for this class must be manually assigned before calling save() when 'cascade' is executed in ClaimReturnInfo .

Is it possible to map Claim Id into ClaimReturnInfo Id or should we do this manually?

Even if we set this ID manually on claimReturnInfo and we can perform updates, we still get this error when trying to create a new Claim:

// POST -> claimRepository.save() -> Error
{
    "notes": "Some test notes on a new claim",
    "claimReturnInfo": {
        "description": "Test description for a new claimReturnInfo"
    }
}

In the ServiceImplemetation:

@Override
@Transactional
public Claim save(Claim claim) throws Exception {
    if(null != claim.getClaimReturnInfo()) {
        claim.getClaimReturnInfo().setId(claim.getIdClaim());
    }

    Claim claimSaved = claimRepository.save(claim);
    return claimSaved;
}

1条回答
爱情/是我丢掉的垃圾
2楼-- · 2020-05-03 10:47

I have tried using the following mappings and from your comments it was apparent that Json object is populated correctly. I have noticed that the annotation @MapsId is the culprit.If you check the documentation of @MapsId annotation it says

Blockquote

The name of the attribute within the composite key * to which the relationship attribute corresponds. If not * supplied, the relationship maps the entity's primary * key

Blockquote

If you change @MapsId("Claim_idClaim") to @MapsId it will start persisting your entities.

import javax.persistence.*;

@Entity
@Table(name = "CLAIM")
public class Claim {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    @Column(name = "idClaim", unique = true, nullable = false)
    private Long idClaim;
    @Column(name = "notes")
    private String notes;

    @OneToOne(mappedBy = "claim", cascade = CascadeType.ALL, optional = false)
    private ClaimReturnInfo claimReturnInfo;

    public Long getIdClaim() {
        return idClaim;
    }

    public String getNotes() {
        return notes;
    }

    public void setNotes(String notes) {
        this.notes = notes;
    }


    public ClaimReturnInfo getClaimReturnInfo() {
        return claimReturnInfo;
    }

    public void setClaimReturnInfo(ClaimReturnInfo claimReturnInfo) {
        if (claimReturnInfo == null) {
            if (this.claimReturnInfo != null) {
                this.claimReturnInfo.setClaim(null);
            }
        } else {
            claimReturnInfo.setClaim(this);
        }
        this.claimReturnInfo = claimReturnInfo;
    }

}


package com.hiber.hiberelations;

import javax.persistence.*;

@Entity
@Table(name = "CLAIM_RETURN_INFO")
public class ClaimReturnInfo {

    @Id
    @Column(name = "Claim_idClaim")
    private Long childId;


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

    @MapsId
    @OneToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "Claim_idClaim")
    private Claim claim;

    public Long getChildId() {
        return childId;
    }

    public String getDescription() {
        return description;
    }

    public void setDescription(String description) {
        this.description = description;
    }

    public Claim getClaim() {
        return this.claim;
    }

    public void setClaim(Claim claim) {
        this.claim = claim;
    }
}
查看更多
登录 后发表回答