Pregunta

Tengo un problema igual al presentado aquí: Cómo definir un eliminación de cascada inversa en un mapeo de muchos a uno en hibernado

Después de buscar un tiempo, no puedo encontrar una solución decente/limpia para esto. No puedo hacer que la entidad matriz tenga una @Onetomany para el niño, porque se encuentran en diferentes módulos. Quería probar el EntityListener que eliminaría a los niños antes que los padres, pero no puedo porque, nuevamente, se encuentran en diferentes módulos.

¿Alguien sabe una solución limpia para esto? Estoy pensando en usar SuppectJ para escuchar la llamada del método Eliminar del ParentDao, pero esta no es una solución limpia y tendré que implementar una para cada entidad que tenga este tipo de relación con la clase principal.

Este tipo de cascada parece ser una característica básica y estoy decepcionado al ver que Hibernate no lo admite:/

¿Fue útil?

Solución 2

Basado en la respuesta de JB Nizet, cambié mi DAO para tener un DeleteOperationListener (mi implementación de DAO base se basa en "No repita el DAO" [1].) De esta manera tengo una solución genérica en caso de que me encuentre en la misma situación de nuevo. La estructura se ve así:

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);
    }
}

Y mi implementación de hibernación abstracta puedo notificar a los observadores sobre el eliminación.

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

Y ahora tengo una clase diferente que maneja la eliminación de los niños sin necesidad de cambiar el 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

Otros consejos

La respuesta de la pregunta a la que vinculó es correcta. Hibernate solo puede eliminar a los niños al eliminar al padre si el padre conoce a sus hijos.

La única solución es tener el método Eliminar de ParentDao para buscar a todos los hijos de los padres, eliminarlos y luego eliminar el padre mismo.

Si su preocupación es que el ParentDao no debe saber sobre los niños, podría hacerlo desacoplarse y hacer que los ParentDao tengan una lista de PadreDelEdelEnders registrados, que se invocarían antes de eliminar a los padres. El ParentDao solo sabe sobre esta interfaz ParentDeletionListener y permite registrar a varios oyentes. Al comenzar la aplicación, registre un oyente para todo tipo de niño y haga que el oyente elimine a los niños:

public interface ParentDeletionListener {
    void parentWillBeDeleted(Parent parent);
}

public class SomeChildParentDeletionListener implements ParentDeletionListener {
    // ...
    public void parentWillBeDeleted(Parent parent) {
        // search for every SomeChild linked to the given parent
        // and delete them
    }
}

public class ParentDAO {
    private List<ParentDeletionListener> listeners = new CopyOnWriteArrayList();

    public void addParentDeletionListener(ParentDeletionListener listener) {
        this.listeners.add(listener);
    }

    public void deleteParent(Parent p) {
        for (ParentDeletionListener listener : listeners) {
            listener.parentWillBeDeleted(parent);
        }
        session.delete(parent);
    }
}
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top