2011-12-05 7 views
0

У меня есть проблема, что это равно приведенному здесь: how to define an inverse cascade delete on a many-to-one mapping in hibernateHibernate, однонаправленный ManyToOne и стремление к Feature «На Удалить Каскад»

После поиска на некоторое время, я не могу найти приличное/чистое решение для этого. Я не могу иметь родительский объект @OneToMany для ребенка, потому что он находится в разных модулях. Я хотел попробовать EntityListener, который будет удалять дочерние элементы до родителя, но я не могу, потому что они снова находятся в разных модулях.

Кто-нибудь знает, как это сделать? Я подумываю использовать AspectJ для прослушивания вызова метода удаления из ParentDao, но это не чистое решение, и мне придется реализовать его для каждого объекта, который имеет такое отношение к классу Parent.

Этот вид каскада, как представляется, основной функцией и я вроде разочарован в том, что спящий режим не поддерживает:/

+1

Ваши очки ссылку на вопрос, касающийся самая внушительная книга, которую вы прочитали. Ничего общего с Hibernate. Пожалуйста, объясните свою проблему в этом вопросе. –

+0

Извините, увязано это неправильно. Редактирование ссылки. –

ответ

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

2

Ответ на вопрос вы связаны правильно. Hibernate может удалять только дочерние элементы при удалении родителя, если родитель знает о своих дочерних элементах.

Единственное решение заключается в том, чтобы метод удаления ParentDAO выполнял поиск всех дочерних элементов родителя, удалял их и удалял сам родитель.

Если вы обеспокоены тем, что 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); 
    } 
} 
+0

Это другой подход к методу preitele EntityListener # preDelete. Это хорошее решение, но меня беспокоит, что нам нужно сделать что-то подобное в спящем режиме для этой общей проблемы. Спасибо за ответ в любом случае :) –

+0

Вы вынуждены это делать, потому что вы решили не связывать родителя с детьми. –

+0

Я нашел общий способ сделать это. Я отправлю его, когда stackoverflow позволит мне. Спасибо за идею JB :) –

 Смежные вопросы

  • Нет связанных вопросов^_^