1

I followed https://vladmihalcea.com/the-best-way-to-map-a-onetomany-association-with-jpa-and-hibernate/ to map One To Many Relationship

But I'm getting problem to remove orphan.
I'm followed Other answers

  1. https://stackoverflow.com/a/10427536/3425489
  2. https://stackoverflow.com/a/3071125/3425489

To make parent null for child, but I don't have child to set its parent to null.

I'm using Session#saveOrUpdate hibernate specific, In DB I've 3 children, and from view I've 2 children to be updated and want to remove 3rd or last one, How to deal with that situation?

My Code snippet as follows:

Entity Class SRS

@Entity
@Table(name="srs")
public class SRS implements Serializable {
    [...]

    @OneToMany( mappedBy="srs"/*, cascade=CascadeType.ALL*/, orphanRemoval=true )
    @Cascade(value={CascadeType.SAVE_UPDATE, CascadeType.REMOVE, CascadeType.REFRESH, CascadeType.MERGE})
    private List<SrsRequirement> srsRequirements = new ArrayList<>();

    public void addRequirement( SrsRequirement srsRequirement ) {
        this.srsRequirements.add( srsRequirement );
        srsRequirement.setSrs( this );
    }
    public void  removeRequirement( SrsRequirement srsRequirement ) {
        this.srsRequirements.remove( srsRequirement );
        srsRequirement.setSrs( null );
    }

    [...]
}

Entity Class SrsRequirement

@Entity
@Table( name="srs_requirement" )
public class SrsRequirement implements Serializable {

    [...]

    @ManyToOne( fetch=FetchType.LAZY )
    @JoinColumn( name="srs_id" )
    private SRS srs;

    [...]

    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + ((id == null) ? 0 : id.hashCode());
        return result;
    }
    @Override
    public boolean equals(Object obj) {
        if (this == obj)
            return true;
        if (obj == null)
            return false;
        if (getClass() != obj.getClass())
            return false;
        SrsRequirement other = (SrsRequirement) obj;
        if (id == null) {
            if (other.id != null)
                return false;
        } else if (!id.equals(other.id))
            return false;
        return true;
    }
}

Code To save and Update from DAO

@Override
public boolean saveOrUpdateSRS( SRS srs ) {
    Session session = null;
    Transaction transaction = null;
    boolean isSaved = false;
    List<SrsRequirement> srsRequirements = srs.getSrsRequirements();
    try {
        session = getSession();
        transaction = session.beginTransaction();
        session.saveOrUpdate( srs );
        session.flush();
        srs.setSrsRequirements( session.get( SRS.class, srs.getId() ).getSrsRequirements() );
        for( SrsRequirement srsRequirement : srs.getSrsRequirements() ) {
            System.out.println( srsRequirement.toString() );
            if( !srsRequirements.contains( srsRequirement ) )
                srs.removeRequirement( srsRequirement );
        }
        if( transaction!= null && transaction.getStatus().equals(TransactionStatus.ACTIVE) )
            transaction.commit();
        isSaved = true;
    } catch ( Exception ex ) {

    } finally{

    }
    return isSaved;
}

Update
I have solved this by session.clear(), and then session.load(), and get all requirements check them and then remove orphan.

Following is working code snippet

session = getSession();
transaction = session.beginTransaction();
session.saveOrUpdate( srs );
session.flush();session.clear();
srs = session.load( SRS.class, srs.getId() );
for( Iterator<SrsRequirement> iterator = srs.getSrsRequirements().iterator(); iterator.hasNext(); ) {
    SrsRequirement srsRequirement = iterator.next();
//          System.out.println( srsRequirement.toString() );
    if( !srsRequirements.contains( srsRequirement ) ) {
//              srs.removeRequirement( srsRequirement );
        iterator.remove();
        srsRequirement.setSrs( null );
    }
}

But the problem with this code, is it issues multiple select statements, which should be optimized

Instead of doing this should I execute separate HQL query to delete rest of srsRequirements, this will execute single query then
Or any other solution ?

Shantaram Tupe
  • 1,646
  • 3
  • 16
  • 42

0 Answers0