I created several similar threads about particular issues, but let me summarize the problem I'm facing more globally:
GOAL
Need to intercept all Insert/Update/Delete DB Transactions in an application written in Spring 4.1.5, Hibernate 4.3.8. The app uses all styles of Hibernate usage:
- Object-based through Session, e.g.
sessionFactory.getCurrentSession().saveOrUpdate(obj);
- HQL executeUpdate, e.g.
Query q = "update Obj ..."; q.executeUpdate();
- Criteria API, e.g.
Criteria q = sessionFactory.getCurentSession().createCriteria(..); q.list();
Possible Approaches
- Interceptor: Implement an Interceptor.
public class MyInterceptor extends EmptyInterceptor {..}
Override either (1) Transaction-level methods or (2) specific action methods.
Transaction-level:
@Override
public void afterTransactionBegin(Transaction tx) {
super.afterTransactionBegin(tx);
}
Specific action level:
@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: Implement a
PreUpdateEventListener
,PreInsertEventListener
and register it.@Component public class HibernateSaveUpdateEventListener implements PreUpdateEventListener, PreInsertEventListener { @Override public boolean onPreInsert(PreInsertEvent arg0) { //... } @Override public boolean onPreUpdate(PreUpdateEvent arg0) { //... } }
Problems
- Neither the
EventListener
norInterceptor
approach intercepts HQL executeUpdate(). But we have many instances of that in the app. Some other users have confirmed that:
https://forum.hibernate.org/viewtopic.php?f=1&t=1012054
https://coderanch.com/t/669945/java/Hibernate-interceptor-working-hibernate-query
Seems like the issue is that EventListener/Interceptor
only work with a Session
. But HQL executeUpdate is on the Query
object, not the Session
.
- Can't use the Transaction-level Interceptor approach of
afterTransactionBegin(Transaction tx)
either. The reason is, I can't distinguish Read-Only Select Transactions from Write Transactions.tx
doesn't tell me whether I'm in areadOnly=false
orreadOnly=true
transaction. So theafterTransactionBegin
override will fire for all transactions, and I need to limit it non-Read-Only ones only (Insert, Update, Delete).
@Transactional(readOnly = false)
@Transactional(readOnly = true)
So is there a solution to comprehensively intercept Insert/Update/Delete for a Hibernate app that uses both object operations and HQL operations?