0

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;
}
canillas
  • 414
  • 3
  • 13
  • yes, you need to save `claim` first – bananas Dec 11 '19 at 09:19
  • Of course if I save `claim` first and I set manually this Id to its childs, it works. I'm asking for an automatic behaviour. – canillas Dec 11 '19 at 09:22
  • are you using `Spring Rest Repositories`? please add code where it fails. \ – bananas Dec 11 '19 at 09:29
  • Do you mean `Spring data repository`? Yes, I'm using `JpaRepository`. The code that fails is simply a `.save` as I said in the question. – canillas Dec 11 '19 at 09:33
  • I think this post should help https://stackoverflow.com/questions/57116212/org-hibernate-id-identifiergenerationexception-attempted-to-assign-id-from-nul/57119049#57119049 .You need to add the setter method in the parent entity so that it can bind the child on fly for you. – user06062019 Dec 11 '19 at 11:44
  • Tank you but this example is not what i'm looking for. My relations are correctly binded by Spring. If you analyze the example, the parent entity hasn't children and the child entity has no `Cascade` defined. I want to store the parent and automatically save children not the other way. – canillas Dec 12 '19 at 09:41

1 Answers1

1

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;
    }
}
user06062019
  • 681
  • 4
  • 9