BLOG

Hibernate Interceptor para auditar entidades

21 de fevereiro de 2010

hibernate_interceptor


Buscando uma solução para um problema, acabei achando uma coisa interessante, bastante útil e que muito projetos poderiam utilizar.


Às vezes se quer realizar alguma auditoria em tabelas antes que as operações sejam efetivadas(comitadas). Operações antes de inserts, updates, deletes, geração de logs e etc. Isso é possível implementando um Interceptor com a vantagem de não ser necessário alterar seu código.

Para um exemplo simples, iremos adicionar a entidade, as propriedades para que seja feita a auditoria.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
@Entity
public EntidadeAuditada implements Serializable {
 
  @Id
  @GeneratedValue (strategy = GenerationType.IDENTITY)
  Long id
 
  @Version
  Long version
 
  @Column (name = "entry_text")
  String text
 
  @Temporal (TemporalType.TIMESTAMP)Date publishedOn
 
  String createdBy
  Date createdOn
  String updatedBy
  Date updatedOn
}


Utilizando a estratégia ImprovedNamingStrategy os para nomes de atributos, que serão traduzidos de createdBy para created_by.


Para criar um interceptor é preciso implementar um Interceptor ou melhor estender EmptyInterceptor para implementar apenas os métodos que realmente interessam.


Como exemplo, utilizo para quando uma entidade for inserida(save) e deletada(delete), sejam alterados as propriedades createBy, createdOn e updatedBy, updatedOn respectivamente, conforme mostrado no código abaixo:


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
public class EntidadeInterceptor extends EmptyInterceptor {
 
  boolean onDelete(Object entity, Serializable id, Object[] currentState,
                      Object[] previousState, String[] propertyNames,
                      Type[] types) {
    setValue(currentState, propertyNames, "updatedBy", UserUtils.getCurrentUsername());
    setValue(currentState, propertyNames, "updatedOn", new Date());
    return true;
  }
 
  boolean onSave(Object entity, Serializable id, Object[] state,
                 String[] propertyNames, Type[] types) {
    setValue(state, propertyNames, "createdBy", UserUtils.getCurrentUsername());
    setValue(state, propertyNames, "createdOn", new Date());
    return true;
  }
 
  private void setValue(Object[] currentState, String[] propertyNames,
                        String propertyToSet, Object value) {
    def index = propertyNames.toList().indexOf(propertyToSet)
    if (index >= 0) {
      currentState[index] = value
    }
  }
}


E depois implementamos o método setValue para fazer realmente o “trabalho” de setar o valor(UserUtils.getCurrentUsername()) na propriedade(createdBy), por exemplo.


Para configurar o interceptor é preciso habilitá-lo no Hibernate Session, podendo ser habilitado globalmente através do SessionFactory ou para uma Session específica como no código a seguir:


1
2
3
4
5
6
7
8
9
10
// Configure interceptor globally (applies to all Sessions)
sessionFactory =
  new AnnotationConfiguration()
    .configure()
    .setNamingStrategy(ImprovedNamingStrategy.INSTANCE)
    .setInterceptor(new EntidadeInterceptor())
    .buildSessionFactory()
 
// Enable per Session
Session session = getSessionFactory().openSession(new EntidadeInterceptor())


Se estiver utilizando o framework como Spring fica ainda mais simples de habilitar o interceptor globalmente, adicionado ao applicationContext.xml(arquivo de configuração do Spring):


1
2
3
4
5
6
7
8
 
<bean id="sessionFactory"
      class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
  <property name="entityInterceptor">
    <bean class="net.valdemarjr.interceptors.EntidadeInterceptor"/>
  </property>
  <!-- additional Hibernate configuration properties -->
</bean>

Bom fica a dica aí, esse post tem como fonte dzone.com

Públicado em: Blog,Java - Tags:, - Autor:Valdemar

Sem cometários »

Sem comentários. Seja o primeiro!

Comenta aí!

Se você quiser um Avatar legal, registre o seu no Gravatar