Domanda

Ho un problema che è uguale a quello presentato qui: come definire una cascata inversa eliminare su una mappatura molti-to-one in letargo

Dopo aver cercato un po 'non riesco a trovare una soluzione decente/pulita per questo. Non posso avere l'entità genitore avere un @onetomany per il bambino, perché sono a diversi moduli. Volevo provare l'EntityListener che avrebbe eliminato i bambini prima che lo fosse il genitore, ma non posso perché, ancora una volta, sono a diversi moduli.

Qualcuno sa una soluzione pulita a questo? Sto pensando di usare AspectJ per ascoltare la chiamata del metodo Elimina del ParentDAO, ma questa non è una soluzione pulita e dovrò implementarne una per ogni entità che ha questo tipo di relazione con la classe genitore.

Questo tipo di cascata sembra essere una caratteristica di base e sono deluso nel vedere che Hibernate non lo supporta:/

È stato utile?

Soluzione 2

Basato sulla risposta di JB Nizet ho cambiato il mio DAO per avere un EleteOperationListener (la mia implementazione di Base DAO si basa su "Non ripetere il DAO" [1].) In questo modo ho una soluzione generica nel caso in cui mi trovo nella stessa di nuovo situazione. La struttura sembra così:

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

E la mia implementazione di Hibernate astratta posso avvisare gli osservatori sull'elimina.

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

E ora ho una classe diversa che gestisce la cancellazione dei bambini senza dover cambiare i 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-genericda.html

Altri suggerimenti

La risposta della domanda a cui hai collegato è corretta. Hibernate può eliminare i bambini solo durante l'eliminazione del genitore se il genitore conosce i suoi figli.

L'unica soluzione è quella di avere il metodo Elimina del genitore per cercare tutti i figli del genitore, eliminarli e quindi eliminare il genitore stesso.

Se la tua preoccupazione è che il genitore non debba sapere dei bambini, potresti renderlo disaccoppiato e far sì che il genitore abbia un elenco di listener genitorierition registrati, che verrebbe invocato prima di eliminare il genitore stesso. Il genitore sa solo di questa interfaccia ParentDeletonListener e consente di registrare più ascoltatori. Quando si avvia l'applicazione, registra un ascoltatore per ogni tipo di bambino e chiedi all'ascoltatore di eliminare i bambini:

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);
    }
}
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top