2
votes

HIbernate - ids for this class must be manually assigned before calling save

object references an unsaved transient instance - save the transient instance before flushing

I have a drop down option in my xhtml page. Sometimes a user needs to select this drop down ,
Sometimes he does not need to select the drop down value.

I have two related entities, one a main table and a column(NULL) in the main table has a reference table. I'm trying to save the data in the table.

The error is : Caused by : javax.el.ELException: /jsf/submit.xhtml @20,76 listener="#{BankLocationMB.saveLocation}" object references an unsaved transient instance - save the transient instance before flushing

Tried adding a cascade Persist I received the error below

org.springframework.orm.jpa.JpaSystemException: org.hibernate.id.IdentifierGenerationException: ids for this class must be manually assigned before calling save(): bank.entity.BankLocation.RefLoan; nested exception is javax.persistence.PersistenceException: org.hibernate.id.IdentifierGenerationException: ids for this class must be manually assigned before calling save(): bank.entity.BankLocation.RefLoan


@Entity
@Table(name = "BANK_LOCATION", schema = "OWNR")
public class BankLocation implements Serializable {

    private static final long serialVersionUID = 1L;
    @Id
    @Basic(optional = false)
    @NotNull
    @Column(name = "BANK_LOCATION_ID")
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "BANK_LOCATION_ID_SEQ")
    @SequenceGenerator(name = "BANK_LOCATION_ID_SEQ", sequenceName = "OWNR.BANK_LOCATION_ID_SEQ", allocationSize = 1)
    private Long bankLocationId;
    @Size(max = 32)
    @Column(name = "BANK_NAME")
    private String bankName;
    
    
    
    @JoinColumn(name = "LOAN_ID", referencedColumnName = "LOAN_ID", insertable = false, updatable = false)
    @ManyToOne(targetEntity=RefLoan.class, optional = true)
    private RefLoan loan;
    public RefLoan getLoan() {
        return loan;
    }
    public void setLoan(RefLoan loan) {
        this.loan = loan;
    }
    
    
    @Override
    public int hashCode() {
        int hash = 0;
        hash += (bankLocationId != null ? bankLocationId.hashCode() : 0);
        return hash;
    }
    @Override
    public boolean equals(Object object) {
        // TODO: Warning - this method won't work in the case the id fields are not set
        if (!(object instanceof BankLocation)) {
            return false;
        }
        BankLocation other = (BankLocation) object;
        if ((this.bankLocationId == null && other.bankLocationId != null) || (this.bankLocationId != null && !this.bankLocationId.equals(other.bankLocationId))) {
            return false;
        }
        return true;
    }
    @Override
    public String toString() {
        return "bank.entity.BankLocation[ bankLocationId=" + bankLocationId + " ]";
    }
    
}


Reference Table Entity


@Entity
@Table(name = "REF_LOAN", schema = "OWNR")

public class RefLoan implements Serializable {

    private static final long serialVersionUID = 1L;
    @Id
    @Basic(optional = false)
    @NotNull
    @Column(name = "LOAN_ID")
    private Integer loanId;
    @Basic(optional = false)
    @NotNull
    @Size(min = 1, max = 50)
    @Column(name = "DISPLAY_NAME")
    private String displayName;
    @Size(max = 50)
    @Column(name = "DESCRIPTION")
    private String description;


    public RefLoan() {
    }

    public RefLoan(Integer loanId) {
        this.loanId = loanId;
    }

    public RefLoan(Integer loanId, String displayName) {
        this.loanId = loanId;
        this.displayName = displayName;
    }

    public Integer getLoanId() {
        return loanId;
    }

    public void setLoanId(Integer loanId) {
        this.loanId = loanId;
    }

    public String getDisplayName() {
        return displayName;
    }

    public void setDisplayName(String displayName) {
        this.displayName = displayName;
    }

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


    @Override
    public int hashCode() {
        int hash = 0;
        hash += (loanId != null ? loanId.hashCode() : 0);
        return hash;
    }

    @Override
    public boolean equals(Object object) {
        if (!(object instanceof RefLoan)) {
            return false;
        }
        RefLoan other = (RefLoan) object;
        if ((this.loanId == null && other.loanId != null) || (this.loanId != null && !this.loanId.equals(other.loanId))) {
            return false;
        }
        return true;
    }

    @Override
    public String toString() {
        return "bank.entity.RefLoan[ loanId=" + loanId + " ]";
    }
    
}

Could anyone provide a fix where I'm going wrong?

Thanks

2

2 Answers

0
votes

This is the important part of the error message: ids for this class must be manually assigned before calling save(): bank.entity.BankLocation.RefLoan

In your Refloan class the ID is not marked as automatically generated:

@Id
@Basic(optional = false)
@NotNull
@Column(name = "LOAN_ID")
private Integer loanId;

You need to add the annotations you have used in your BankLocation class (after adjusting the name of the sequence accordingly)

@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "BANK_LOCATION_ID_SEQ")
@SequenceGenerator(name = "BANK_LOCATION_ID_SEQ", sequenceName = "OWNR.BANK_LOCATION_ID_SEQ", allocationSize = 1)
0
votes

You probably have some code similar to the following:

entityManager.merge(bankLocation);

You will have to use a managed reference for the loan, like this:

if (bankLocation.getRefLoan() != null) {
    bankLocation.setRefLoan(entityManager.getReference(RefLoan.class, bankLocation.getRefLoan().getId());
}
entityManager.merge(bankLocation);