Auditoria: Hibernate Envers
Autor: Fábio Medeiros Faria | Publicado: 2012-03-12T22:28:00-03:00

Olá seguidores e entusiastas do SerJava!!

Faz certo tempo que não os alimento de conteúdo, mas tenham certeza que não abandonei o blog nem o interesse em disseminar p conhecimento e, acima de tudo, propagar a tecnologia Java.

Desde que comecei a trabalhar no ecossistema Java, confesso, sempre tive uma queda pelas tecnologias relativas a ORM (Mapeamento Objeto-Relacional); gostos a parte, optei como artigo de retomada, abordar sobre o HibernateEnvers.

Comumente, desde pequenas a grandes aplicações, tem-se o desejo (necessidade realmente) de monitorar as ações do usuário frente ao sistema, de modo a prover controle sobre o uso da aplicação, bem como, resguardar a integridade das informações administradas pela mesma. Por certo, a maioria das aplicações desenvolvidas sobre a plataforma Java, fazem uso de frameworks ORM. Aproveitando os preceitos desta tecnologia, diga-se de passagem, já abordados em tópicos anteriores (mas ainda há mais conteúdos, aguardem!), o Hibernate dispões do subprojeto Envers.

O Hibernate Envers "provê o histórico de versionamento dos dados manipulados pela aplicação", ou seja, é possível fazer uso de objetos persistentes (entidades mapeadas para a persistência JPA) para auditar as modificações havidas num dado registro. O Envers, utiliza de artifícios de revisões, conceito similar ao subservion. Sua configuração é bastante simples, bastando a adição do jar correspondente ao classpath e a configuração do arquivo persistence.xml.

No intuito de ser objetivo, neste tópico vou abordar apenas os primeiros passos, novos posts trarão mais detalhes sobre o Envers.

Implementação

Aproveitando o conteúdo já trabalhado, a respeito de persistência nos posts anteriores, farei uso do projeto criado até então, onde foi realizado o mapeamento para a persistência de objetos representativos de um Produto (http://www.serjava.blogspot.com/2011/12/persistencia-jpa-dao-generico.html).

Como o projeto foi feito há um tempinho (rsrs) resolvi modernizar inserindo a última versão do Hibernate, a 4.0, disponível em:&nbsp;Hibernate Download, feito o download, observe que o diretório lib contém: envers, jpa, &nbsp;required e optional. Para atualizar seu hibernate, delete todos os artefatos do seu projeto, exceto o driver de conexão com o banco (caso esteja utilizando o projeto iniciado anteriormente) e adicione os jars dos diretórios: envers, jpa e required no classpath da sua aplicação (o primeiro post sobre JPA mostra como fazer). Seu classpath, neste momento, deverá conter:


O próximo passo é adicionarmos a configuração do Envers, faremos a auditória, até então, apenas para a criação e atualização de dados, assim, seu arquivo persistence.xml, deverá ficar similar a este:
&lt;?xml version="1.0" encoding="UTF-8"?&gt;
&lt;persistence version="2.0"
 xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd"&gt;
 &lt;persistence-unit name="PersistenciaPU"
  transaction-type="RESOURCE_LOCAL"&gt;

  &lt;provider&gt;org.hibernate.ejb.HibernatePersistence&lt;/provider&gt;
  &lt;class&gt;br.com.serjava.persistencia.entity.Produto&lt;/class&gt;

  &lt;properties&gt;
   &lt;property name="hibernate.connection.username" value="postgres" /&gt;
   &lt;property name="hibernate.connection.driver_class" value="org.postgresql.Driver" /&gt;
   &lt;property name="hibernate.connection.password" value="123456" /&gt;
   &lt;property name="hibernate.connection.url" value="jdbc:postgresql://localhost:5432/PERSISTENCIA" /&gt;
   &lt;property name="hibernate.show_sql" value="true" /&gt;
   
   &lt;!-- Permite operacoes ddls pelo jpa --&gt;
   &lt;property name="hibernate.hbm2ddl.auto" value="update" /&gt;

   &lt;!-- configuracao do Envers --&gt;
   &lt;property name="post-insert" value="org.hibernate.ejb.event.EJB3PostInsertEventListener, org.hibernate.envers.event.EnversListener" /&gt;
   &lt;property name="post-update" value="org.hibernate.ejb.event.EJB3PostUpdateEventListener, org.hibernate.envers.event.EnversListener" /&gt;
  &lt;/properties&gt;

 &lt;/persistence-unit&gt;
&lt;/persistence&gt;



O próximo passo, é marcarmos a entidade que deverá ser auditada, no caso Produto, apenas anotando-a com @Audited:
package br.com.serjava.persistencia.entity;
//import omitidos
@Entity
@Audited
@AuditTable(value="PRODUTO_AUDIT")
@Table(name="produto")
@SequenceGenerator(name="produto_id_produto_seq", sequenceName="produto_id_produto_seq", allocationSize=1)
public class Produto implements Serializable {
 @Id
 @GeneratedValue(generator="produto_id_produto_seq", strategy=GenerationType.SEQUENCE)
 @Column(name="id_produto")
 private Integer idProduto;
 
 @Column(name="nm_produto")
 private String nomeProduto;
 
 @Column(name="quantidade")
 private Integer quantidade;
 
 @Column(name="valor")
 private Double valor;

 //getters and setters
}

A anotação @Audited diz ao Envers que esta entidade deverá ser auditada, e @AuditTable, discrimina, explicitamente, o nome da tabela a ser gerada que deverá conter as revisions dos dados.

Feito isto, execute a classe main, já implementado do projeto anterior, em seguida, acesso o banco postgres, e verifique a criação das tabelas: produto_audit e revinfo:



Pronto! Sua entidade produto já está sendo auditada, a pártir de agora, nas operações de inserção e atualização. Faça mais testes, com alterações. Nos próximos posts, demonstrarei como as revisions são organizadas e, como recuperar as revisões de um registro.

Espero que tenham gostado!