我遇到的问题与此处提出的问题相同:how to define an inverse cascade delete on a many-to-one mapping in hibernate
经过一段时间的搜索,我无法找到一个体面/干净的解决方案。我不能让父实体对子项有@OneToMany,因为它们位于不同的模块中。我想尝试在父级之前删除子级的EntityListener,但我不能再这样了,因为它们位于不同的模块中。
有谁知道这个干净的解决方案?我正在考虑使用AspectJ来监听来自ParentDao的delete方法的调用,但这不是一个干净的解决方案,我将不得不为每个与Parent类有这种关系的实体实现一个。
这种级联似乎是一个基本功能,我很沮丧地看到hibernate不支持它:/
答案 0 :(得分:2)
您链接的问题的答案是正确的。如果父节点知道它的子节点,Hibernate只能在删除父节点时删除子节点。
唯一的解决方案是让ParentDAO的delete方法搜索父级的所有子级,删除它们,然后删除父级本身。
如果你担心的是ParentDAO不应该知道这些孩子,你可以让它解耦,让ParentDAO有一个已注册的ParentDeletionListeners列表,在删除父本身之前会调用它们。 ParentDAO只知道这个ParentDeletionListener接口,并允许注册多个监听器。启动应用程序时,为每种类型的子节点注册一个侦听器,并让侦听器删除子节点:
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);
}
}
答案 1 :(得分:1)
根据JB Nizet的回答,我改变了我的DAO以使用DeleteOperationListener(我的基础DAO实现基于“不要重复DAO”[1]。)这样我有一个通用的解决方案,以防我发现自己在同样的情况下再次。结构如下所示:
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);
}
}
我的抽象hibernate实现我可以通知观察者有关删除的内容。
@Override
public void delete(T entityToDelete) {
notifyPreDelete(entityToDelete);
this.getHibernateTemplate().delete(entityToDelete);
notifyPosDelete(entityToDelete);
}
现在我有一个不同的类来处理孩子的删除而无需更改DAO:
@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