Search code examples
hibernatespring-mvcjacksoncascading-deletes

Hibernate cascade="all-delete-orphan", doesn't delete orphans


I am having trouble deleting orphan nodes using Hibernate with the following mapping

@OneToMany(fetch = FetchType.LAZY, mappedBy = "seizure",orphanRemoval=true)
@JsonManagedReference  
@Cascade({CascadeType.ALL,CascadeType.DELETE_ORPHAN})
public Set<SubstanceIdentified> getSubstanceIdentifieds() {
    return this.substanceIdentifieds;
}

the .hbm.xml mapping is like this

  <set name="substanceIdentifieds" table="substance_identified" inverse="true" lazy="true" fetch="select" cascade="all-delete-orphan">
        <key>
            <column name="seizure_id"  not-null="true" />
        </key>
        <one-to-many class="org.unodc.incbszdb.db.base.SubstanceIdentified" />
    </set>

I use Spring MVC and Jackson to do the JSON to Hibernate Class mapping

 @RequestMapping(value = { "/save.json" }, method = RequestMethod.POST)
 public ModelMap save(@RequestBody Seizure seizureObj, Model model) {
    seizureService.saveOrUpdate(seizureObj);


NOTE:

seizureObj has only two NEW entries in its substanceIdentifieds Set.

The id property of seizureObj is set to an existing record in the db. But when I call saveOrUpdate existing records (orphans) don't get deleted.



Seizure Service uses Spring's

getHibernateTemplate.saveOrUpdate

I have read the threads about

JPA CascadeType.ALL does not delete orphans
Hibernate deleting orphans when updating collection

It seems my setup is right.

Do I have to

  1. load the according object from the DB in a dummy object object first (with the ID my de-serialized object has)
  2. delete the references to other object
  3. save the changes
  4. update with my de-serialized object

?


Solution

  • Acutally it is possible to do it without calling clear.

    All I had to do is calling the right function.

    use HibernateDaoSupport.getHibernateTemplate().merge(object)

    In my code I first test if the de-serialized object from jackson has a ID attached

    if so I call save, if not I call merge.

    if(obj.getId()){
       myDAO.save(obj);
    }else{
       myDAO.merge(obj);
    }
    

    and the merge function of my DAO is defined like this.

    public void merge(E transientObject) {
      getHibernateTemplate().merge(transientObject);
    }
    

    This deletes the orphans like it is supposed to be.

    If somebody is facing the same problem do not hesitate, I am open to help you with it.

    Regards JS