Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/hibernate/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Hibernate、单向manytone和对“On Delete Cascade”功能的渴望_Hibernate_Many To One_Hibernate Cascade - Fatal编程技术网

Hibernate、单向manytone和对“On Delete Cascade”功能的渴望

Hibernate、单向manytone和对“On Delete Cascade”功能的渴望,hibernate,many-to-one,hibernate-cascade,Hibernate,Many To One,Hibernate Cascade,我有一个问题与这里的问题相同: 搜索了一段时间后,我找不到合适/干净的解决方案。我不能让父实体与子实体有@OneToMany,因为它们位于不同的模块。我想尝试EntityListener,它会在父级之前删除子级,但我不能,因为它们位于不同的模块 有人知道一个干净的解决办法吗?我正在考虑使用AspectJ来监听ParentDao中delete方法的调用,但这不是一个干净的解决方案,我必须为与父类具有这种关系的每个实体实现一个 这种级联似乎是一种基本功能,我很失望地看到hibernate不支持它:/

我有一个问题与这里的问题相同:

搜索了一段时间后,我找不到合适/干净的解决方案。我不能让父实体与子实体有@OneToMany,因为它们位于不同的模块。我想尝试EntityListener,它会在父级之前删除子级,但我不能,因为它们位于不同的模块

有人知道一个干净的解决办法吗?我正在考虑使用AspectJ来监听ParentDao中delete方法的调用,但这不是一个干净的解决方案,我必须为与父类具有这种关系的每个实体实现一个


这种级联似乎是一种基本功能,我很失望地看到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 answer,我将我的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);
    }
}
现在我有了一个不同的类,它可以在不改变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]

您的链接指向一个关于您所读过的最有影响的书的问题。与冬眠无关。请在这个问题中解释你的问题。对不起,链接错误的地方。编辑链接。这与EntityListenerpreDelete方法不同。这是一个很好的解决方案,但对于这种常见的问题,我们需要在hibernate中执行类似的操作,这让我感到困扰。不管怎样,谢谢你的回答:你被迫这么做是因为你选择了避免父母和孩子之间的耦合。我找到了一个通用的方法来做到这一点。我会在你允许的时候把它寄出去。谢谢你的想法,JB:
@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
    }
}