Durante o ciclo de vida de um projeto inúmeras operações são realizadas em seu banco de dados. Caso algum dado seja inserido/alterado incorretamente, serão necessários meios para que possamos recuperá-los em sua versão antiga ou identificar o autor daquela alteração. Para isso surgiu a necessidade de ferramentas de auditória/versionamento de entidades.

O que é o Hibernate Envers ?

O Envers é um projeto que habilita a auditória/versionamento de classes persistentes de uma maneira fácil. Ele trabalha com o conceito de revisões, similar ao do Subversion, onde cada transação é uma revisão (desconsiderando as transações que não modificam as entidades auditadas). A partir da versão 3.5 do Hibernate, o Envers foi incluído como um de seus core modules. Para sua auditória funcionar corretamente, as entidades precisam ter identificadores imutáveis (primary-keys). Você pode usar o Envers em qualquer ambiente que o Hibernate funcione: sendo standalone, dentro do JBoss AS, com o JBoss Seam ou Spring.

Primeiro Passo - Criação do Projeto

1 - Com o banco de dados instalado e inicializado, abra sua IDE (estaremos utilizando o Eclipse)

2 - Crie um projeto JPA (File > New > JPA Project) e realize toda a configuração da JPA com o banco de dados:

Criação de Projeto JPA

Segundo Passo - Adicionando Bibliotecas Necessárias

1 - Conforme informado anteriormente, a partir da versão 3.5 do Hibernate o Envers foi incluído como um de seus core modules. Para baixar basta acessar a página de downloads do Hibernate, estarei utilizando a versão 4.3.6.Final.

2 - Estarei utilizando também o banco de dados H2, por ser fácil e rápido de instalar e configurar. Para baixar seu driver JDBC basta acessar a sua página de downloads, estarei utilizando a sua versão 1.4.181.

3 - Com as bibliotecas necessárias baixadas e extraídas, criaremos um diretório lib dentro do projeto e adicionaremos todas as bibliotecas necessárias:

Bibliotecas

4 - Após adicionar todas as bibliotecas dentro da pasta lib, basta fazer uma referência (selecione as libs e com o botão direito do mouse sobre as libs vá em > Build Path > Add To Build Path) para elas no BuildPath do projeto.

Terceiro Passo - Realizando Configurações Essenciais

Agora precisamos realizar alterações no persistence.xml para que o Envers funcione corretamente. Para isso, abra o persistence.xml e configure as informações básicas de seu banco de dados e os listeners para para o funcionamento do Envers:

<persistence-unit name="EnversProject">
	<provider>org.hibernate.ejb.HibernatePersistence</provider>
	
	<!-- Entidades -->
	<class>com.adrianolisboa.entidade.Produto</class>
 
	<properties>
		<property name="hibernate.connection.driver_class" value="org.h2.Driver" /> 
		<property name="hibernate.connection.username" value="envers" />
		<property name="hibernate.connection.password" value="1234" />
		<property name="hibernate.connection.url" value="jdbc:h2:/home/somes/Desenvolvimento/databases/envers" />
		<property name="hibernate.show_sql" value="true" />
		<property name="hibernate.hbm2ddl.auto" value="update" />
		
		<!-- Configuração do Hibernate Envers -->
		<property name="post-insert" value="org.hibernate.ejb.event.EJB3PostInsertEventListener, org.hibernate.envers.event.EnversListener" />
		<property name="post-update" value="org.hibernate.ejb.event.EJB3PostUpdateEventListener, org.hibernate.envers.event.EnversListener" />
	</properties>
</persistence-unit>

Quarto Passo - Codificação das Entidades

Para que as entidades possam ser auditadas é preciso adicionar a anotação @Audited em cada uma delas, opcionalmente também podemos adicionar a anotação @AuditTable e definir um nome para a tabela de auditória que o envers deverá criar (por padrão, se não informado, ele criará uma tabela com o nome da entidade seguido de _AUD).

Anotações na Entidade

Quinto Passo - Testes

Após todo o processo de configuração, precisamos executar alguns inserts ou updates na entidade anotada, para isso criamos uma classe simples e realizamos algumas operações:

public class Principal {

	public static void main(String[] args) {

	EntityManagerFactory emf = Persistence.createEntityManagerFactory("EnversProject");
	EntityManager em = emf.createEntityManager();
	
	em.getTransaction().begin();
	
	Produto produto = new Produto();
	produto.setNome("Meu Produto 1");
	produto.setDescricao("Teste de Produto 1");
	produto.setPreco(new BigDecimal(1.0));
	
	Produto produto2 = new Produto();
	produto2.setNome("Meu Produto 2");
	produto2.setDescricao("Teste de Produto 2");
	produto2.setPreco(new BigDecimal(1.0));
	
	em.persist(produto);
	em.persist(produto2);
	em.getTransaction().commit();
	
	em.getTransaction().begin();
	
	Produto produtoAlterado = new Produto();
	produtoAlterado.setId(1);
	produtoAlterado.setNome("Produto 1 Alterado");
	produtoAlterado.setDescricao("Teste de Produto 1 Alterado");
	produtoAlterado.setPreco(new BigDecimal(2.0));
	
	em.merge(produtoAlterado);
	em.getTransaction().commit();
	
	em.close();
	emf.close();
	}
}

Agora ao verificarmos o nosso banco de dados, duas novas tabelas foram criadas:

Banco de Dados Final

Verifique o conteúdo destas tabelas e notará que a cada operação executada é gravada uma nova revisão.

Conclusão

Quando se trata de auditória/versionamento de entidades, o Hibernate Envers cumpre o prometido. Sua configuração é rápida e a documentação disponível é bastante rica.

Projeto

Baixe aqui o código fonte do projeto desenvolvido.

Fontes:

http://envers.jboss.org/