Hibernate EmptyInterceptor onFlushDirty()没有执行 [英] Hibernate EmptyInterceptor onFlushDirty() is not executing
问题描述
我想为我的实体更新进行审计。所以我实现了 EmptyInterceptor 。
我的 onFlushDirty()
方法没有执行,但 afterTransactionCompletion()
执行
Hibernate 5.0
+
我没有做任何配置而不是 @组件
在配置文件中直到 afterTransactionCompletion()
得到执行。
我在这里缺少什么?
同样如何拦截事件 query.executeUpdate()
?
我的Interceptor类如下:
@Component
public class AuditLogInterceptor extends EmptyInterceptor {
private static final long serialVersionUID = 1L;
@Override
public boolean onFlushDirty(Object entity,Serializable id,
Object [] currentState,Object [] previousState,
String [] propertyNames,Type []类型){
System.out.println(AuditLogInterceptor.onFlushDirty());
System.out.println();
System.out.println(Property Names: - ); (String propertyName:propertyNames)
{
System.out.print(,+ propertyName);
}
System.out.println();
System.out.println(当前状态: - );
for(Object current:currentState){
System.out.print(,+ String.valueOf(current));
}
System.out.println();
System.out.println(Previous State: - );
for(Object previous:previousState){
System.out.print(,+ String.valueOf(previous));
}
返回true;
// return super.onFlushDirty(entity,id,currentState,previousState,
// propertyNames,types);
}
@Override
public void afterTransactionCompletion(Transaction tx){
// TODO自动生成的方法存根
System.out.println(AuditLogInterceptor.afterTransactionCompletion( ));
super.afterTransactionCompletion(tx);
@Override
public boolean onSave(Object entity,Serializable id,Object [] state,
String [] propertyNames,Type [] types){
System .out.println( AuditLogInterceptor.onSave());
System.out.println(属性名称: - + Arrays.toString(propertyNames));
System.out.println(States: - + Arrays.toString(state));
返回super.onSave(实体,id,状态,propertyNames,类型);
@Override
public void postFlush(@SuppressWarnings(rawtypes)迭代器实体){
System.out.println();
System.out.println(AuditLogInterceptor.postFlush()); ();
for(; entities.hasNext();){
System.out.println(-----+ entities.next()。getClass()。getSimpleName());
}
System.out.println();
super.postFlush(entities);
}
}
代码在我的DAO中
@Override
public boolean updateAssignment(Integer workTaskDetailId,short workTaskStatus){
Session session = null;
交易交易=空;
布尔isUpdated = false;
尝试{
session = this.sessionFactory.withOptions()。interceptor(new AuditLogInterceptor()).openSession();
transaction = session.beginTransaction();
String COMPLETION_DATE =;
if(workTaskStatus == 263)
COMPLETION_DATE =,wtd.completionDate =:completionDate;
final String UPDATE_WORKTASKSTATUS =update WorkTaskDetail wtd set wtd.workTaskStatus =:workTaskStatus
+ COMPLETION_DATE +其中wtd.workTaskDetailId =:workTaskDetailId;
Query query = session.createQuery(UPDATE_WORKTASKSTATUS).setShort(workTaskStatus,workTaskStatus)
.setInteger(workTaskDetailId,workTaskDetailId);
if(workTaskStatus == 263)
query.setDate(completionDate,new Date());
int updateCount = query.executeUpdate();
if(updateCount> 0)
isUpdated = true;
if(session!= null)
session.flush();
if(transaction!= null&& transaction.getStatus()。equals(TransactionStatus.ACTIVE))
transaction.commit();
} catch(Exception exception){
if(transaction!= null&& transaction.getStatus()。equals(TransactionStatus.ACTIVE))
transaction.rollback();
LOGGER.error(Message: - + exception.getMessage());
LOGGER.error(根本原因: - + exception.getCause());
LOGGER.error(***************************************** *******************);
} finally {
if(session!= null)
session.close();
}
return isUpdated;
onFlushDirty
方法未被调用,因为当前正在运行的持久性上下文没有修改实体。 当我在本文中进行了解释,只有托管实体可以生成自动UPDATE语句。在你的情况下,你正在执行一个手动的SQL UPDATE,这超出了Hibernate的范围
因此,您有两种选择:
- 使用 Hibernate Envers ,因为不需要在Hibernate之上编写自制的审计日志。
- 使用 Debezium因为数据库已经具有审计日志(又名WAL,重做日志,事务日志)。
I want to do Audit for my entity updates. So I have implemented EmptyInterceptor.
My onFlushDirty()
method is not executing, but afterTransactionCompletion()
does executes
I'm using Spring 4.1 and Hibernate 5.0
+
I have not done any configuration rather than @Component
in configuration file till afterTransactionCompletion()
get executed.
What I'm missing here ?
Also how to intercept Event query.executeUpdate()
?
My Interceptor class is as follows:
@Component
public class AuditLogInterceptor extends EmptyInterceptor {
private static final long serialVersionUID = 1L;
@Override
public boolean onFlushDirty(Object entity, Serializable id,
Object[] currentState, Object[] previousState,
String[] propertyNames, Type[] types) {
System.out.println("AuditLogInterceptor.onFlushDirty()");
System.out.println();
System.out.println("Property Names :- ");
for (String propertyName : propertyNames) {
System.out.print(", "+propertyName);
}
System.out.println();
System.out.println("Current State :- ");
for (Object current : currentState) {
System.out.print(", "+ String.valueOf( current ) );
}
System.out.println();
System.out.println("Previous State :- ");
for (Object previous : previousState) {
System.out.print(", "+ String.valueOf( previous ) );
}
return true;
//return super.onFlushDirty(entity, id, currentState, previousState,
//propertyNames, types);
}
@Override
public void afterTransactionCompletion(Transaction tx) {
// TODO Auto-generated method stub
System.out.println("AuditLogInterceptor.afterTransactionCompletion()");
super.afterTransactionCompletion(tx);
}
@Override
public boolean onSave(Object entity, Serializable id, Object[] state,
String[] propertyNames, Type[] types) {
System.out.println("AuditLogInterceptor.onSave()");
System.out.println("Property Names :- "+Arrays.toString(propertyNames));
System.out.println("States :- "+Arrays.toString(state));
return super.onSave(entity, id, state, propertyNames, types);
}
@Override
public void postFlush(@SuppressWarnings("rawtypes") Iterator entities) {
System.out.println();
System.out.println("AuditLogInterceptor.postFlush()");
for ( ; entities.hasNext() ;) {
System.out.println("-----"+ entities.next().getClass().getSimpleName());
}
System.out.println();
super.postFlush(entities);
}
}
Code In my DAO
@Override
public boolean updateAssignment( Integer workTaskDetailId, short workTaskStatus ) {
Session session = null;
Transaction transaction = null;
boolean isUpdated = false;
try {
session = this.sessionFactory.withOptions().interceptor( new AuditLogInterceptor() ).openSession();
transaction = session.beginTransaction();
String COMPLETION_DATE = "";
if( workTaskStatus == 263 )
COMPLETION_DATE = ", wtd.completionDate = :completionDate ";
final String UPDATE_WORKTASKSTATUS = "update WorkTaskDetail wtd set wtd.workTaskStatus = :workTaskStatus "
+COMPLETION_DATE+ "where wtd.workTaskDetailId = :workTaskDetailId ";
Query query = session.createQuery(UPDATE_WORKTASKSTATUS).setShort("workTaskStatus", workTaskStatus)
.setInteger("workTaskDetailId", workTaskDetailId);
if( workTaskStatus == 263 )
query.setDate("completionDate", new Date() );
int updateCount = query.executeUpdate();
if( updateCount > 0 )
isUpdated = true;
if( session != null )
session.flush();
if( transaction != null && transaction.getStatus().equals(TransactionStatus.ACTIVE) )
transaction.commit();
} catch ( Exception exception ) {
if( transaction != null && transaction.getStatus().equals( TransactionStatus.ACTIVE) )
transaction.rollback();
LOGGER.error("Message :- "+exception.getMessage());
LOGGER.error("Root Cause :- "+exception.getCause());
LOGGER.error(" ************************************************************");
} finally {
if( session != null )
session.close();
}
return isUpdated;
}
The onFlushDirty
method was not called because there was no entity being modified by the currently running Persistence Context.
As I explained in this article, only managed entities can generate automatic UPDATE statements. In your case, you are executing a manual SQL UPDATE, which is beyond the scope of Hibernate entity state transitions.
Therefore, you have two choices:
- Use Hibernate Envers as there is no need to write a homemade Audit Log on top of Hibernate.
- Use Debezium since the DB already features an Audit Log anyway (a.k.a. WAL, redo log, transaction log).
这篇关于Hibernate EmptyInterceptor onFlushDirty()没有执行的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!