使用Interceptor审计hibernate中的新旧值

时间:2010-02-08 05:25:56

标签: database hibernate audit-trail

我可以轻松记录上次修改日期,修改日期等。但是,我还需要记录旧值和新值。在拦截器中,我可以在postflush开始执行之前触发一个select来获取当前记录的值。然后我可以在此记录和新记录之间运行差异以查看更改的内容并将该信息记录为旧值和新值。有没有更好的办法?

问题是我修改的对象对于其他对象也可能非常庞大。做差异可能很昂贵。

-Thanks

5 个答案:

答案 0 :(得分:3)

覆盖onFlushDirty EmptyInterceptor(IInterceptor),为您提供数组previousState和currentState。您可以使用这两个数组来查找oldvalue和newvalue。

look at this example

答案 1 :(得分:0)

为什么不使用审计表和触发器?

答案 2 :(得分:0)

你可以试试Envers,它现在是Hibernate的一部分:http://www.jboss.org/envers

答案 3 :(得分:0)

我这样审核,但日期很难看:

persistence.xml:property name="hibernate.ejb.interceptor" value="siapen.jpa.interceptor.MeuInterceptador" />

    package siapen.jpa.interceptor;

import java.io.Serializable;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Iterator;

import org.apache.commons.lang3.ObjectUtils;
import org.hibernate.CallbackException;
import org.hibernate.EmptyInterceptor;
import org.hibernate.type.Type;

import siapen.model.BaseEntity;

public class MeuInterceptador extends EmptyInterceptor {

    private static final long serialVersionUID = 7853236444153436270L;

    private String strSQL = "";
    String acao;
    @SuppressWarnings("rawtypes")
    BaseEntity entity;
    String s = "";

    @SuppressWarnings("unchecked")
    // 1
    public boolean onSave(Object obj, Serializable id, Object[] valores, String[] propertyNames, Type[] types)
            throws CallbackException {
        if (obj instanceof BaseEntity) {
            entity = (BaseEntity) obj;
            for (int i = 0; i < valores.length; i++) {
                if (valores[i] != null && !valores[i].equals("")) {
                    s += propertyNames[i] + ":" + valores[i];
                    if (i != valores.length - 1) {
                        s += "___";
                    }
                }
            }
        }
        return false;
    }

    @SuppressWarnings("unchecked")
    // 1
    public boolean onFlushDirty(Object obj, Serializable id, Object[] valoresAtuais, Object[] valoresAnteriores,
            String[] propertyNames, Type[] types) throws CallbackException {
        if (obj instanceof BaseEntity) {
            entity = (BaseEntity) obj;

            for (int i = 0; i < valoresAtuais.length; i++) {

                if (!ObjectUtils.equals(valoresAtuais[i], valoresAnteriores[i])) {
                    if (!s.equals("")) {
                        s += "___";
                    }
                    s += propertyNames[i] + "-Anterior:" + valoresAnteriores[i] + ">>>Novo:" + valoresAtuais[i];
                }
            }
        }
        return false;

    }

    @SuppressWarnings("unchecked")
    // 1
    public void onDelete(Object obj, Serializable id, Object[] state, String[] propertyNames, Type[] types) {
        if (obj instanceof BaseEntity) {
            entity = (BaseEntity) obj;
        }
    }

    // CHAMADO ANTES DO COMMIT
    // 2
    @SuppressWarnings("rawtypes")
    public void preFlush(Iterator iterator) {
    }

    // 3
    public String onPrepareStatement(String sql) {
        acao = "";
        if (sql.startsWith("/* update")) {
            acao = "update";
        } else if (sql.startsWith("/* insert")) {
            acao = "insert";
        } else if (sql.startsWith("/* delete")) {
            acao = "delete";
        }
        if (acao != null) {
            strSQL = sql;
        }
        return sql;
    }

    // CHAMADO APÓS O COMMIT
    // 4
    @SuppressWarnings("rawtypes")
    public void postFlush(Iterator iterator) {
        if (acao != null) {
            try {
                if (acao.equals("insert")) {
                    AuditLogUtil audi = new AuditLogUtil();
                    audi.LogIt("Salvo", entity, s);
                }
                if (acao.equals("update")) {
                    AuditLogUtil audi = new AuditLogUtil();
                    audi.LogIt("Atualizado", entity, s);
                }
                if (acao.equals("delete")) {
                    AuditLogUtil audi = new AuditLogUtil();
                    audi.LogIt("Deletado", entity, "");
                }

            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                strSQL = "";
                s = "";
            }
        }
    }

}

答案 4 :(得分:0)

对于使用Envers的用户,可以使用自定义Envers侦听器轻松实现。它也可能是更清洁的解决方案。

  1. 实施自定义evnvers集成器并注册您的听众(查看envers docs
  2. 实施更新/插入侦听器
  3. public class UpdateEnversListener extends EnversPostUpdateEventListenerImpl {
    
        private static Logger log = LoggerFactory.getLogger(UpdateEnversListener.class);
    
        public UpdateEnversListener(EnversService enversService) {
            super(enversService);
        }
    
        @Override
        public void onPostUpdate(PostUpdateEvent event) {
    
            List<String> auditedProperties = Arrays.asList(event.getPersister().getPropertyNames());
                List<Integer> dirtyFieldsIndices = Ints.asList(event.getDirtyProperties());
    
            // In the event you have a object
            // In the persister you have indices of fields that changed and also their values
            // Do your magic  stuff here 
    
    
            super.onPostUpdate(event);
        }
    }