Я создал несколько похожих тем о конкретных проблемах, но позвольте мне обобщить проблему, с которой я сталкиваюсь более глобально:
ЗАДАЧА
Необходимо перехватить все операции вставки / обновления / удаления БД в приложении, написанном на 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?