0

I understand that this question has been asked a lot of times on this forum but i believe sometimes there are new kind of issues coming up. This one might be a type. So i have this code with a parent child entity. The relationship between parent to child is one-to-many joined through some column. The Cascade type is ALL(tried with others as well). The generation strategy is sequence which implies Hibernate assigns it at the time of insertion. Now with the insertion of multiple records with id as null, i get this NonUniqueObjectException with Session complaining about another identifier. I have tried with a lot of trials but none to the point that the child gets inserted. If Cascade is removed completely, the process runs good but child indeed is not inserted. Here are my entities and also the records which i am trying to insert. What i need: 1. How to let hibernate know it is a different object( in my case equals method is not being used by hibernate somehow and i dont know where hibernate uses it tbh. As my Column Two has a different value, they are indeed different objects as per equals, hashcode. 2.How can i insert a child later but update reference in parent.

Parent entity

@Entity
@Table(name = "PARENT_ENTITY")
public class ParentEntity implements Serializable {

private static final long serialVersionUID = 6072072740006570718L;

@Id
@SequenceGenerator(name = "ResultSeqPE", sequenceName = "SEQ_PARENT_ENTITY", allocationSize = 1)
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "ResultSeqPE")
private Integer id;



@Column(name = "PE_DATE", nullable = false, updatable = false)
private LocalDate date;

@Column(name = "COL1", nullable = false, updatable = false)
private Double ColumnOne;

@Column(name = "COL2", updatable = false)
private Double ColumnTwo;

@Column(name = "COL3", updatable = false)
private Double ColumnThree;

@OneToMany(mappedBy = "childEntityCol", fetch = FetchType.EAGER, cascade=CascadeType.ALL)
private List<ChildEntity> childEntyValues = new ArrayList<>();

@Transient
private final int numOfFactors=5;

@Column(name = "COL4", nullable = true)
private String ColumnFour;

public String getColumnFour() {
    return ColumnFour;
}

public void setColumnFour(String ColumnFour) {
    this.ColumnFour = ColumnFour;
}

public ParentEntity(){}

public ParentEntity(LocalDate date, Double ColumnThree, String ColumnFour){
   this( date, ColumnThree, null, null,ColumnFour);
}

public ParentEntity( LocalDate date, Double ColumnThree, Double ColumnTwo, Double ColumnOne, String ColumnFour){
    this.date = date;
    this.ColumnThree = ColumnThree;
    this.ColumnTwo = ColumnTwo;
    this.ColumnOne = ColumnOne;
    this.ColumnFour=ColumnFour;
}


public Integer getId() {
    return id;
}

public void setId(Integer id) {
    this.id = id;
}




public LocalDate getDate() {
    return date;
}

public void setDate(LocalDate date) {
    this.date = date;
}


public List<ChildEntity> getChildEntyValues() {
    return childEntyValues;
}

public void setChildEntyValues(List<ChildEntity> childEntyValues) {
    this.childEntyValues = childEntyValues;
}


public Double getColumnOne() {
    return ColumnOne;
}

public void setColumnOne(Double ColumnOne) {
    this.ColumnOne = ColumnOne;
}


public Double getColumnTwo() {
    return ColumnTwo;
}

public void setColumnTwo(Double ColumnTwo) {
    this.ColumnTwo = ColumnTwo;
}


public Double getColumnThree() {
    return ColumnThree;
}

public void setColumnThree(Double ColumnThree) {
    this.ColumnThree = ColumnThree;
}


@Override
public String toString() {
    return "ParentEntity{" +
            "id=" + id +
            ", date=" + date +
            ", ColumnOne=" + ColumnOne +
            ", ColumnTwo=" + ColumnTwo +
            ", ColumnThree=" + ColumnThree +
            ",ColumnFour=" + ColumnFour+
           '}';
}

@Override
public boolean equals(Object o) {
    if (this == o) return true;

    if (!(o instanceof ParentEntity)) return false;

    ParentEntity that = (ParentEntity) o;

    return new EntityEqualsBuilder()
            .append(numOfFactors, that.numOfFactors)
            .append(ColumnFour, that.ColumnFour)
            .append(getDate(), that.getDate())
            .append(getColumnOne(), that.getColumnOne())
            .append(getColumnTwo(), that.getColumnTwo())
            .append(ColumnThree, that.ColumnThree)
            .isEquals();

}

@Override
public int hashCode() {
    return new HashCodeBuilder(17, 37)
            .append(getDate())
            .append(getColumnOne())
            .append(getColumnTwo())
            .append(numOfFactors)
            .append(ColumnFour)
            .toHashCode();
}
}

Child Entity

import org.apache.commons.lang3.builder.HashCodeBuilder;

import java.io.Serializable;

import javax.persistence.*;
import javax.validation.constraints.Size;

@Entity
@Table( name = "CHILD_ENTITY")
public class ChildEntity implements Serializable {


/**
 * 
 */
private static final long serialVersionUID = 8229169287136307307L;


@Id
@SequenceGenerator(name = "ResultValueSeqCHLD", sequenceName = "SEQ_CHILD_ENTITY", allocationSize = 20)
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "ResultValueSeqCHLD")
private Integer id;

@Column(name = "COL1")
private String ChildColumnOne;

@Size(max = 100)
@Column(name = "COL2", nullable = false, updatable = false)
private String ChildColumnTwo;

@Column(name = "COL3", nullable = false, updatable = false)
private Double ChildColumnThree;

//Standard deviation
@Column(name = "COL4", nullable = true)
private Double ChildColumnFour;

@Column(name = "COL5", nullable = true)
private String ChildColumnFive;


public String getChildColumnFive() {
    return ChildColumnFive;
}

public void setChildColumnFive(String ChildColumnFive) {
    this.ChildColumnFive = ChildColumnFive;
}

@ManyToOne(fetch=FetchType.EAGER)
@JoinColumn(name = "RESULT_ID", nullable = true, updatable = true)
private ParentEntity childEntityCol;


@Transient
private static final int numOfFactors=5;

public ChildEntity() {
}

public ChildEntity(ParentEntity childEntityCol,
                               String ChildColumnOne,
                               String ChildColumnTwo,
                               Double ChildColumnThree,
                               Double ChildColumnFour,
                               String rmvdfctr) {
    this.childEntityCol = childEntityCol;
    this.ChildColumnOne = ChildColumnOne;
    this.ChildColumnTwo = ChildColumnTwo;
    this.ChildColumnThree = ChildColumnThree;
    this.ChildColumnFour = ChildColumnFour;
    this.ChildColumnFive=rmvdfctr;
}

public Integer getId(){ return id; }

public void setId(Integer id){
    this.id = id;
}

public Double getChildColumnThree() {
    return ChildColumnThree;
}

public void setChildColumnThree(Double ChildColumnThree) {
    this.ChildColumnThree = ChildColumnThree;
}

public String getChildColumnOne() {
    return ChildColumnOne;
}

public void setChildColumnOne(String ChildColumnOne) {
    this.ChildColumnOne = ChildColumnOne;
}

public String getChildColumnTwo() {
    return ChildColumnTwo;
}

public void setChildColumnTwo(String ChildColumnTwo) {
    this.ChildColumnTwo = ChildColumnTwo;
}

public ParentEntity getchildEntityCol() {
    return childEntityCol;
}

public void setchildEntityCol(ParentEntity childEntityCol) {
    this.childEntityCol = childEntityCol;
}

public Double getChildColumnFour() {
    return ChildColumnFour;
}

public void setChildColumnFour(Double ChildColumnFour) {
    this.ChildColumnFour = ChildColumnFour;
}

@Override
public String toString() {
    return "CrossSectionResultValueFiveFactors{" +
            "id=" + id +
            ", ChildColumnOne=" + ChildColumnOne +
            ", ChildColumnTwo='" + ChildColumnTwo + '\'' +
            ", ChildColumnThree=" + ChildColumnThree +
            ", ChildColumnFour=" + ChildColumnFour +
            ", ChildColumnFive=" + ChildColumnFive +
            '}';
}

@Override
public boolean equals(Object o) {

    System.out.println("Equals method called");
    if (this == o) return true;

    if (!(o instanceof ChildEntity)) return false;

    ChildEntity that = (ChildEntity) o;

    if(ChildColumnFive != that.ChildColumnFive){
        return false;
    }

    return new EntityEqualsBuilder()
            .append(ChildColumnFive, that.ChildColumnFive)
            .append(getChildColumnOne(), that.getChildColumnOne())
            .append(childEntityCol.getDate(), that.childEntityCol.getDate())
            .append(numOfFactors, that.numOfFactors)
            .append(getChildColumnTwo(), that.getChildColumnTwo())
            .append(getChildColumnThree(), that.getChildColumnThree())
            .append(getChildColumnFour(), that.getChildColumnFour())
            .isEquals();
}

@Override
public int hashCode() {
    return new HashCodeBuilder(17, 37)
            .append(numOfFactors)
            .append(ChildColumnFive)
            .append(getChildColumnOne())
            .append(getChildColumnTwo())
            .append(getChildColumnThree())
            .append(getChildColumnFour())
            .append(childEntityCol.getDate())
            .toHashCode();
}
}

The records Hibernate is trying to insert for Child entity

    id=null,ChildColumnOne=ARTG,ChildColumnTwo=BB,ChildColumnThree=0.017343977423166613,ChildColumnFour=4.5005492463416223E-4,ChildColumnFive=TENOR
id=null,ChildColumnOne=ARTG,ChildColumnTwo=AA,ChildColumnThree=0.0,ChildColumnFour=null,ChildColumnFive=TENOR
id=null,ChildColumnOne=ARTG,ChildColumnTwo=AAA,ChildColumnThree=-0.0032299113437670047,ChildColumnFour=4.5125704017972683E-4,ChildColumnFive=TENOR
id=null,ChildColumnOne=ARTG,ChildColumnTwo=A,ChildColumnThree=0.00271525070429559,ChildColumnFour=2.68546862862496E-4,ChildColumnFive=TENOR
id=null,ChildColumnOne=ARTG,ChildColumnTwo=CCC,ChildColumnThree=0.06180573527799885,ChildColumnFour=0.0013944546117282551,ChildColumnFive=TENOR
id=null,ChildColumnOne=ARTG,ChildColumnTwo=B,ChildColumnThree=0.035266618793342724,ChildColumnFour=6.903395055330724E-4,ChildColumnFive=TENOR
id=null,ChildColumnOne=ARTG,ChildColumnTwo=BBB,ChildColumnThree=0.006277560784636706,ChildColumnFour=2.9452395925335794E-4,ChildColumnFive=TENOR
id=null,ChildColumnOne=SCTR,ChildColumnTwo=XX,ChildColumnThree=-7.484158323833947E-4,ChildColumnFour=3.209042959626849E-4,ChildColumnFive=TENOR
id=null,ChildColumnOne=SCTR,ChildColumnTwo=YY,ChildColumnThree=0.0010161770578058535,ChildColumnFour=5.450833322608508E-4,ChildColumnFive=TENOR
id=null,ChildColumnOne=SCTR,ChildColumnTwo=ZZ,ChildColumnThree=0.0012685617889754614,ChildColumnFour=4.2303152747200215E-4,ChildColumnFive=TENOR
id=null,ChildColumnOne=SCTR,ChildColumnTwo=PP,ChildColumnThree=-0.0015318036574709301,ChildColumnFour=5.326195888612156E-4,ChildColumnFive=TENOR
id=null,ChildColumnOne=SCTR,ChildColumnTwo=QQ,ChildColumnThree=-6.929110009865118E-4,ChildColumnFour=6.329592108245802E-4,ChildColumnFive=TENOR
id=null,ChildColumnOne=SCTR,ChildColumnTwo=RR,ChildColumnThree=-0.0019122958178337181,ChildColumnFour=3.4641562920409316E-4,ChildColumnFive=TENOR
id=null,ChildColumnOne=SCTR,ChildColumnTwo=SS,ChildColumnThree=-0.0019080966821294664,ChildColumnFour=3.887778671973025E-4,ChildColumnFive=TENOR
id=null,ChildColumnOne=SCTR,ChildColumnTwo=TT,ChildColumnThree=-0.0011255034583223175,ChildColumnFour=2.4576405278469896E-4,ChildColumnFive=TENOR
id=null,ChildColumnOne=SCTR,ChildColumnTwo=UU,ChildColumnThree=-4.083237085957168E-4,ChildColumnFour=3.239432062712418E-4,ChildColumnFive=TENOR
id=null,ChildColumnOne=SCTR,ChildColumnTwo=VV,ChildColumnThree=0.0,ChildColumnFour=null,ChildColumnFive=TENOR
id=null,ChildColumnOne=SCTR,ChildColumnTwo=WW,ChildColumnThree=-0.001826936857448209,ChildColumnFour=0.0012430200943232715,ChildColumnFive=TENOR
id=null,ChildColumnOne=CTRY,ChildColumnTwo=KK,ChildColumnThree=-0.001820836558888903,ChildColumnFour=6.075555350826326E-4,ChildColumnFive=TENOR
id=null,ChildColumnOne=CTRY,ChildColumnTwo=LL,ChildColumnThree=-0.0011289483934925119,ChildColumnFour=0.0011271116946331911,ChildColumnFive=TENOR
id=null,ChildColumnOne=CTRY,ChildColumnTwo=MM,ChildColumnThree=-0.006944573473560388,ChildColumnFour=4.4010977849485424E-4,ChildColumnFive=TENOR

The record at which Session is complaining:

id=null,ChildColumnOne=CTRY,ChildColumnTwo=NN,ChildColumnThree=-0.007162728895175867,ChildColumnFour=4.7163949543625657E-4,ChildColumnFive=TENOR

Here we see a different column two.

Some restrictions: I can only use Sequence as the generator.

Please suggest. I followed vlad's blog and a lot of others in forums but to no success. In my case, it is the records which are itself complaining as per Session.

The exception:

    org.hibernate.NonUniqueObjectException: A different object with the same identifier value was already associated with the session : [com.ing.ipa.dmd.bondproxy.core.model.CrossSectionResultValueFiveFactors#234]
    at org.hibernate.event.internal.AbstractSaveEventListener.performSave(AbstractSaveEventListener.java:165)
    at org.hibernate.event.internal.AbstractSaveEventListener.saveWithGeneratedId(AbstractSaveEventListener.java:121)
    at org.hibernate.event.internal.DefaultSaveOrUpdateEventListener.saveWithGeneratedOrRequestedId(DefaultSaveOrUpdateEventListener.java:192)
    at org.hibernate.event.internal.DefaultSaveEventListener.saveWithGeneratedOrRequestedId(DefaultSaveEventListener.java:38)
    at org.hibernate.event.internal.DefaultSaveOrUpdateEventListener.entityIsTransient(DefaultSaveOrUpdateEventListener.java:177)
    at org.hibernate.event.internal.DefaultSaveEventListener.performSaveOrUpdate(DefaultSaveEventListener.java:32)
    at org.hibernate.event.internal.DefaultSaveOrUpdateEventListener.onSaveOrUpdate(DefaultSaveOrUpdateEventListener.java:73)
    at org.hibernate.internal.SessionImpl.fireSave(SessionImpl.java:678)
    at org.hibernate.internal.SessionImpl.save(SessionImpl.java:670)
CVS
  • 41
  • 6

1 Answers1

0

Hibernate is saying that you have two objects which have the same primary identifier but they are not the same object.

It most often happens via cascading saves where there is a cascade save between ParentEntity and ChildEntity, but ChildEntity has already been associated with the session but not on the same instance of ChildEntity.

nbirla
  • 600
  • 3
  • 14
  • I think that's the intended purpose of cascading saves meant to save child list at the time of saving a parent. What you mean to say is for all Cascading saves, we would have this problem. Can you please elaborate your answer. – CVS Jan 10 '18 at 11:49