1

ここに示したものと同じ問題があります:休止状態の多対1マッピングで逆カスケード削除を定義する方法

しばらく検索した後、私はこれのためのまともな/きれいな解決策を見つけることができません。親エンティティが異なるモジュールにあるため、子に@OneToManyを持たせることはできません。親が削除される前に子を削除するEntityListenerを試してみたかったのですが、やはり、子が異なるモジュールにあるため、できません。

誰かがこれに対するクリーンな解決策を知っていますか?AspectJを使用してParentDaoからのdeleteメソッドの呼び出しをリッスンすることを考えていますが、これはクリーンなソリューションではなく、Parentクラスとこのような関係を持つエンティティごとに1つ実装する必要があります。

この種のカスケードは基本的な機能のようであり、休止状態がそれをサポートしていないことに私は少しがっかりしています:/

4

2 に答える 2

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);
    }
}
于 2011-12-05T11:48:50.387 に答える
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);
    }
}

そして、私の抽象的な休止状態の実装では、削除についてオブザーバーに通知できます。

@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

于 2011-12-06T11:23:47.423 に答える