Search code examples
hibernatemany-to-onehibernate-cascade

Hibernate, unidirectional ManyToOne and the desire for a "On Delete Cascade" Feature


I have a problem that's equal to the one presented here: how to define an inverse cascade delete on a many-to-one mapping in hibernate

After searching for a while I can't find a decent/clean solution for this. I can't have the parent entity have an @OneToMany to the child, because they are at different modules. I wanted to try the EntityListener that would delete the children before the parent is, but I can't because, again, they are at different modules.

Does anyone know a clean solution to this? I am thinking about to use AspectJ to listen to the call of the delete method from the ParentDao, but this is not a clean solution and I will have to implement one for each entity that have this kind of relation to the Parent class.

This kind of cascade seems to be a basic feature and I am kind dissapointed in seeing that hibernate does not support it :/


Solution

  • Based on JB Nizet answer I changed my DAO to have a DeleteOperationListener (My base DAO implementation is based on "Don't Repeat the DAO"[1].) In this way I have a generic solution in case I find myself in the same situation again. The structure looks like this:

    public interface GenericDao<T, PK extends Serializable> {
        // CRUD methods
    
        // delete operation listeners.
        void addDeleteListener(DeleteOperationListener<T, PK> deleteOperationListener);
    
        public interface DeleteOperationListener<T> {
            void preDelete(T entity);
            void posDelete(T entity);
        }
    }
    

    And my abstract hibernate implementation I can notify the observers about the delete.

    @Override
    public void delete(T entityToDelete) {
        notifyPreDelete(entityToDelete);
        this.getHibernateTemplate().delete(entityToDelete);
        notifyPosDelete(entityToDelete);
    }
    

    And now I have a different class that handles the deletion of the children without needing to change the DAOs:

    @Service
    public class ParentModificationListener
        implements GenericDao.DeleteOperationListener<Parent> {
    
        private ChildDao childDao;
    
        @Autowired
        public ParentModificationListener(ChildDao childDao, ParentDao parentDao) {
            this.childDao = childDao;
            parentDao.addDeleteListener(this);
        }
    
        @Override
        public void preDelete(Parent parent) {
            this.childDao.deleteChildrenFromParent(parent);
        }
    
        @Override
        public void posDelete(Parent parent) {
            // DO NOTHING
        }
    }
    

    [1] http://www.ibm.com/developerworks/java/library/j-genericdao.html