0

I am developing a code using jpa on existing database tables(in Oracle), in which I am stuck into a issue of deleting a child of a child of an entity.

Let me give you the snippets :

Grandparent entity :

package com.blah.blah.jpa;

import java.io.Serializable;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;
import javax.persistence.SequenceGenerator;
import javax.persistence.Table;

@Entity
@Table(name = "BD_SETUP")
public class BDSetup implements Serializable {

    private static final long serialVersionUID = 1L;

    @Id
    @GeneratedValue(generator = "BD_SETUP_SEQ", strategy = GenerationType.SEQUENCE)
    @SequenceGenerator(name = "BD_SETUP_SEQ", sequenceName = "BD_SETUP_SEQ", allocationSize = 1)
    @Column(name = "ID")
    private Long id;

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "BD_SECURITY_ID", insertable = true, updatable = false)
    private BDSecurity bdSecurity;

    @Column(name = "IS_ENABLED")
    private String isEnabled;

    @Column(name = "IS_FULL_LOAD")
    private String isFullLoad;

    @Column(name = "LAST_RUN_BEGIN")
    private Timestamp lastRunBegin;

    @Column(name = "LAST_RUN_END")
    private Timestamp lastRunEnd;

    @Column(name = "NEXT_RUN_BEGIN")
    private Timestamp nextRunBegin;

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

    @Column(name = "COMMENTS")
    private String comments;

    @OneToMany(mappedBy = "bdSetup", fetch = FetchType.LAZY, cascade = {CascadeType.ALL}, orphanRemoval = true)
    private Set<BDExtractSetup> bdExtractSetups = new HashSet<BDExtractSetup>();

    public Long getId() {
        return id;
    }
    public void setId(Long id) {
        this.id = id;
    }
    public BDSecurity getBdSecurity() {
        return bdSecurity;
    }
    public void setBdSecurity(BDSecurity bdSecurity) {
        this.bdSecurity = bdSecurity;
    }
    public String getIsEnabled() {
        return isEnabled;
    }
    public void setIsEnabled(String isEnabled) {
        this.isEnabled = isEnabled;
    }
    public String getIsFullLoad() {
        return isFullLoad;
    }
    public void setIsFullLoad(String isFullLoad) {
        this.isFullLoad = isFullLoad;
    }
    public Timestamp getLastRunBegin() {
        return lastRunBegin;
    }
    public void setLastRunBegin(Timestamp lastRunBegin) {
        this.lastRunBegin = lastRunBegin;
    }
    public Timestamp getLastRunEnd() {
        return lastRunEnd;
    }
    public void setLastRunEnd(Timestamp lastRunEnd) {
        this.lastRunEnd = lastRunEnd;
    }
    public Timestamp getNextRunBegin() {
        return nextRunBegin;
    }
    public void setNextRunBegin(Timestamp nextRunBegin) {
        this.nextRunBegin = nextRunBegin;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public String getComments() {
        return comments;
    }
    public void setComments(String comments) {
        this.comments = comments;
    }
    public Set<BDExtractSetup> getBdExtractSetups() {
        return bdExtractSetups;
    }
    public void setBdExtractSetups(Set<BDExtractSetup> bdExtractSetups) {
        this.bdExtractSetups = bdExtractSetups;
    }
    @Override
    public String toString() {
        return "BDSetup [id=" + id + ", bdSecurity=" + bdSecurity
                + ", isEnabled=" + isEnabled + ", isFullLoad=" + isFullLoad
                + ", lastRunBegin=" + lastRunBegin + ", lastRunEnd="
                + lastRunEnd + ", nextRunBegin=" + nextRunBegin + ", name="
                + name + ", comments=" + comments + "]";
    }
}

Son Entity (mapped table with extra column):

package com.blah.blah.jpa;

import java.io.Serializable;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import javax.persistence.CascadeType;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;
import javax.persistence.SequenceGenerator;
import javax.persistence.Table;

@Entity
@Table(name = "BD_EXTRACT_SETUP")
public class BDExtractSetup implements Serializable {
private static final long serialVersionUID = 1L;

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

// bi-directional many-to-one association to BDSetup 
@ManyToOne
@JoinColumn(name = "BD_SETUP_ID", referencedColumnName="ID", nullable = false)
private BDSetup bdSetup;

// bi-directional many-to-one association to BDExtract
@ManyToOne
@JoinColumn(name = "BD_EXTRACT_ID", referencedColumnName="ID", nullable = false)
private BDExtract bdExtract;

@OneToMany(mappedBy = "bdExtractSetup", fetch = FetchType.LAZY, cascade = CascadeType.ALL, orphanRemoval = true)
private Set<BDExtractSetupColumn> bdExtractSetupColumn = new HashSet<BDExtractSetupColumn>();

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

public Long getId() {
    return id;
}

public BDSetup getBdSetup() {
    return bdSetup;
}

public void setBdSetup(BDSetup bdSetup) {
    this.bdSetup = bdSetup;
}

public void setBdExtract(BDExtract bdExtract) {
    this.bdExtract = bdExtract;
}

public BDExtract getBdExtract() {
    return bdExtract;
}

public void setExtractAndSetup(BDExtract bdExtract, BDSetup bdSetup) {
    this.bdExtract = bdExtract;
    this.bdSetup = bdSetup;

}

public Set<BDExtractSetupColumn> getBdExtractSetupColumn() {
    return bdExtractSetupColumn;
}

public void setBdExtractSetupColumn(
        Set<BDExtractSetupColumn> bdExtractSetupColumn) {
    this.bdExtractSetupColumn = bdExtractSetupColumn;
}
}

Grandson entity (mapped table with extra column):

package com.blah.blah.jpa;

import java.io.Serializable;

import javax.persistence.Column;
import javax.persistence.EmbeddedId;
import javax.persistence.Entity;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.MapsId;
import javax.persistence.Table;

@Entity
@Table(name = "BD_EXTRACT_SETUP_COLUMN")
public class BDExtractSetupColumn implements Serializable {

private static final long serialVersionUID = 1L;

@EmbeddedId
private BDExtractSetupColumnId id = new BDExtractSetupColumnId();

@ManyToOne
@MapsId("bdExtractSetupId")
@JoinColumn(name = "BD_EXTRACT_SETUP_ID", referencedColumnName = "ID", nullable = false)
private BDExtractSetup bdExtractSetup;

@ManyToOne
@MapsId("bdExtractColumnId")
@JoinColumn(name = "BD_EXTRACT_COLUMN_ID", referencedColumnName = "ID", nullable = false)
private BDExtractColumn bdExtractColumn;

@Column(name = "DISPLAY_ORDER")
private Long displayOrder;

/**
 * @return the id
 */
public BDExtractSetupColumnId getId() {
    return id;
}

/**
 * @param id the id to set
 */
public void setId(BDExtractSetupColumnId id) {
    this.id = id;
}

/**
 * @return the bdExtractSetup
 */
public BDExtractSetup getBdExtractSetup() {
    return bdExtractSetup;
}

/**
 * @param bdExtractSetup the bdExtractSetup to set
 */
public void setBdExtractSetup(BDExtractSetup bdExtractSetup) {
    this.bdExtractSetup = bdExtractSetup;
}

/**
 * @return the bdExtractColumn
 */
public BDExtractColumn getBdExtractColumn() {
    return bdExtractColumn;
}

/**
 * @param bdExtractColumn the bdExtractColumn to set
 */
public void setBdExtractColumn(BDExtractColumn bdExtractColumn) {
    this.bdExtractColumn = bdExtractColumn;
}

/**
 * @return the displayOrder
 */
public Long getDisplayOrder() {
    return displayOrder;
}

/**
 * @param displayOrder the displayOrder to set
 */
public void setDisplayOrder(Long displayOrder) {
    this.displayOrder = displayOrder;
}
}

There is code which tries to delete the children as follows, I am able to get bdSetup and all its contents.

Set<BDExtractSetup> bdExtractSetups = bdSetup.getBdExtractSetups();
bdExtractSetups.clear();
bdSetupDAO.save(bdSetup);

And DAO as :

package com.blah.blah.jpa.dao;

import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;

import com.blah.blah.jpa.BDSecurity;
import com.blah.blah.jpa.BDSetup;

@Repository
public interface BDSetupDAO extends JpaRepository<BDSetup, Long>{

public BDSetup findByBdSecurityAndName(BDSecurity bdSecurity, String name);

}

I am trying to update the bdSetup with :

if(isUpdate) {

        Set<BDExtractSetup> bdExtractSetups = bdSetup.getBdExtractSetups();

        for (BDExtractSetup bdExtractSetup : bdSetup.getBdExtractSetups()) {
            bdExtractSetup.getBdExtractSetupColumn().clear();
        }
//          bdExtractSetups.clear();
//          bdExtractSetupDAO.delete(bdSetup.getBdExtractSetups());
            bdSetup.getBdExtractSetups().clear();
//          bdSetup = bdSetupDAO.getOne(bdSetup.getId());

//          bdExtractSetupDAO.deleteInBatch(bdExtractSetups);

//          bdSetup = bdSetupDAO.findOne(bdSetup.getId());


        for (int i = 0; i < bdExtracts.size(); i++) {

            BDExtract bdExtract = bdExtracts.get(i);

            BDExtractSetup bdExtractSetup = new BDExtractSetup();
            bdExtractSetup.setBdSetup(bdSetup);
            bdExtractSetup.setBdExtract(bdExtract);

            Set<BDExtractSetupColumn> tempExtractSetupColumns = new HashSet<BDExtractSetupColumn>();

            for (BDExtractDTO bdExtractDTO : mappedBdExtracts) {

                if(bdExtract.getId().equals(bdExtractDTO.getId())) {
                    BDExtractColumn extractColumn = null;
                    BDExtractSetupColumn extractSetupColumn = null;
                    for (BDExtractColumnDTO bdExtractColumnDTO : bdExtractDTO.getBdExtractColumns()) {
                        extractColumn = new BDExtractColumn();
                        extractColumn.setName(bdExtractColumnDTO.getName());
                        extractColumn.setBdExtract(bdExtract);

                        extractSetupColumn = new BDExtractSetupColumn();
                        extractSetupColumn.setBdExtractColumn(extractColumn);
                        extractSetupColumn.setBdExtractSetup(bdExtractSetup);
                        extractSetupColumn.setDisplayOrder(bdExtractColumnDTO.getDisplayOrder());

                        tempExtractSetupColumns.add(extractSetupColumn);
                    }
                    break; //if bdExtractId matches the id in mappedBdExtracts, do not iterate further for bdExtractColumns of extractDTO
                }
            }
            bdExtractSetup.getBdExtractSetupColumn().addAll(tempExtractSetupColumns);
            finalBDExtractSetups.add(bdExtractSetup);
        }
        bdSetup.getBdExtractSetups().addAll(finalBDExtractSetups);
    }
    return finalBDExtractSetups;

Previous exception is gone, now getting other exception as :

Hibernate: 
insert 
into
    BD_EXTRACT_SETUP
    (BD_EXTRACT_ID, BD_SETUP_ID, id) 
values
    (?, ?, ?)
31 May 2015 10:08:24,256 [main] WARN  org.hibernate.engine.jdbc.spi.SqlExceptionHelper  - SQL Error: 1, SQLState: 23000
 31 May 2015 10:08:24,256 [main] ERROR org.hibernate.engine.jdbc.spi.SqlExceptionHelper  - ORA-00001: unique constraint (BI_DATA.BD_EXTRACT_SETUP_UN1) violated

 31 May 2015 10:08:24,262 [main] INFO  org.hibernate.engine.jdbc.batch.internal.AbstractBatchImpl  - HHH000010: On release of batch it still contained JDBC statements

This means, deletion is not happening, direct insert query is fired. Any solution please?

Thanks.

raggsss
  • 41
  • 5

1 Answers1

0

It seems that you are assigning a new collection instance to a managed entity instance somewhere.

You can find more info about this here, here and here.

Community
  • 1
  • 1
Dragan Bozanovic
  • 23,102
  • 5
  • 43
  • 110
  • Thanks for replying, I tried bdSetup.getBdExtractSetups().clear() and bdSetup.getBdExtractSetups().addAll(finalBDExtractSetups); now the exception is `org.hibernate.engine.jdbc.spi.SqlExceptionHelper - ORA-00001: unique constraint (BI_DATA.BD_EXTRACT_SETUP_UN1) violated` it means delete query is not fired on BdExtractSetups, but with direct insert query on bdSetup. Why deletion is not happening on BdExtractSetups after clearing the set and setting new set finalBDExtractSetups? – raggsss May 31 '15 at 04:22