Как полностью перехватить операции вставки / обновления / удаления БД в приложении Hibernate 4 - PullRequest
0 голосов
/ 16 ноября 2018

Я создал несколько похожих тем о конкретных проблемах, но позвольте мне обобщить проблему, с которой я сталкиваюсь более глобально:

ЗАДАЧА

Необходимо перехватить все операции вставки / обновления / удаления БД в приложении, написанном на Spring 4.1.5, Hibernate 4.3.8. Приложение использует все стили использования Hibernate:

  • Объектно-через сеанс, например, sessionFactory.getCurrentSession().saveOrUpdate(obj);
  • HQL executeUpdate, например Query q = "update Obj ..."; q.executeUpdate();
  • Критерии API, например Criteria q = sessionFactory.getCurentSession().createCriteria(..); q.list();

Возможные подходы

  • Перехватчик : Реализация перехватчика.

public class MyInterceptor extends EmptyInterceptor {..}

Переопределить либо (1) методы уровня транзакции, либо (2) конкретные методы действия.

Транзакция уровня:

@Override
    public void afterTransactionBegin(Transaction tx) {                 
        super.afterTransactionBegin(tx);            
    }

Уровень специальных действий :

@Override
public boolean onSave(Object entity, Serializable id, Object[] state, String[] propertyNames, Type[] types) {
    return super.onSave(entity, id, state, propertyNames, types);
}

@Override
public void onDelete(Object entity, Serializable id, Object[] state, String[] propertyNames, Type[] types) {
    super.onDelete(entity, id, state, propertyNames, types);
}
  • EventListener : Реализуйте PreUpdateEventListener, PreInsertEventListener и зарегистрируйте его.

    @Component
    public class HibernateSaveUpdateEventListener implements PreUpdateEventListener, PreInsertEventListener  {
        @Override
        public boolean onPreInsert(PreInsertEvent arg0) {
            //...
        }
        @Override
        public boolean onPreUpdate(PreUpdateEvent arg0) {
          //...
        }
    }
    

Проблемы

  • Ни подход EventListener, ни Interceptor не перехватывает HQL executeUpdate () . Но у нас есть много примеров этого в приложении. Некоторые другие пользователи подтвердили, что:

https://forum.hibernate.org/viewtopic.php?f=1&t=1012054

https://coderanch.com/t/669945/java/Hibernate-interceptor-working-hibernate-query

Похоже, проблема в том, что EventListener/Interceptor работает только с Session. Но HQL executeUpdate находится на объекте Query, а не Session.

  • Также нельзя использовать метод перехватчика уровня транзакции afterTransactionBegin(Transaction tx). Причина в том, что я не могу отличить транзакции выбора только для чтения от транзакций записи. tx не сообщает мне, участвую ли я в транзакции readOnly=false или readOnly=true. Поэтому переопределение afterTransactionBegin сработает для всех транзакций, и мне нужно ограничить его только для чтения (вставка, обновление, удаление).

@Transactional(readOnly = false) @Transactional(readOnly = true)

Так есть ли решение для всестороннего перехвата вставки / обновления / удаления для приложения Hibernate, которое использует как объектные операции, так и операции HQL?

...