休眠,单向ManyToOne以及对"On Delete Cascade"功能的渴望



我遇到了一个和这里一样的问题:如何在hibernate中的多对一映射上定义反向级联删除

搜索了一段时间后,我找不到一个像样的/干净的解决方案。我不能让父实体有一个@OneToMany到子实体,因为它们在不同的模块。我想尝试EntityListener,将删除父之前的孩子,但我不能,因为,再一次,他们在不同的模块。

有人知道一个干净的解决方案吗?我正在考虑使用AspectJ来监听来自ParentDao的删除方法的调用,但这不是一个干净的解决方案,我将不得不为每个与Parent类有这种关系的实体实现一个。

这种级联似乎是一种基本特性,看到hibernate不支持它,我有点失望:/

你链接到的问题的答案是正确的。如果父类知道它的子类,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);
    }
}

根据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

相关内容

  • 没有找到相关文章

最新更新