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: Hibernate Download, feito o download, observe que o diretório lib contém: envers, jpa, 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:
<?xml version="1.0" encoding="UTF-8"?> <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"> <persistence-unit name="PersistenciaPU" transaction-type="RESOURCE_LOCAL"> <provider>org.hibernate.ejb.HibernatePersistence</provider> <class>br.com.serjava.persistencia.entity.Produto</class> <properties> <property name="hibernate.connection.username" value="postgres" /> <property name="hibernate.connection.driver_class" value="org.postgresql.Driver" /> <property name="hibernate.connection.password" value="123456" /> <property name="hibernate.connection.url" value="jdbc:postgresql://localhost:5432/PERSISTENCIA" /> <property name="hibernate.show_sql" value="true" /> <!-- Permite operacoes ddls pelo jpa --> <property name="hibernate.hbm2ddl.auto" value="update" /> <!-- configuracao do 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> </persistence>
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!
Olá,
ResponderExcluiruma duvida quando digito diretamente no banco de dados via front-end (workbench) não cria registro na tabela produto_audit porque ??? estou fazendo no banco mysql...
Olá Paulo,
ResponderExcluiresta auditoria via Envers é de domínio da aplicação, ou seja, ela se faz presente por todas as ações realizadas dentro da aplicação.
Diretamente pelo banco não é possível mapear pelo envers, ai vc teria que pensar em usar triggers. Não vejo muita ncessidade, pois o usuário não deverá manipular nada diretamente ao banco, exceto se você possuir mais de uma aplicação manipulando o mesmo banco.
Agradeço o interessse ;)
Qualquer dúvida, pode postar!
Fabio faz um post de como adicionar campos na rev info, tipo usuario logado, eu fiz o que eles falaram no site da envers so que a entidade nova que criei nao é ne chamada... complicado isso.. e to precisando urgente disso.
ResponderExcluirOlá Adalberto, desculpe a demora, não tinha reparado no comment.
ExcluirVou tentar priorizá-lo!
Obrigado pela visita, espero que os conteúdos tenham sido do seu interesse.
[]s
Já tentei de tudo e não funciona.
ResponderExcluirColoquei as versões iguais a daqui, o persistence.xml ta igual, anotações iguais
e quando rodo a aplicação, ele cria as tabelas assim como esta aqui
mais na hora que eu salvo ou faço qualquer outra operação, ele não audita nada =//////.... já tentei de tudo.... Algum help?
Rafael, dá uma re-conferida naqueles events, no caso deste post temos 2 eventos, configurados no persistence.xml, que dizem qdo, de fato, a auditoria deve ser realizada. Verifique se o value delas condizem com o que vc está usando.
ExcluirQualquer coisa, poste ai, na medida do possível dou um help.
[]s
Boa tarde.
ResponderExcluirGostaria de saber se tem como eu mudar o banco..
não queria que as tabelas de auditoria ficassem no mesmo banco do sistema..
exemplo
DB_SISTEMA
DB_SISTEMA_AUD
sacou ?
Vlw
Oi, vi teu comment e achei interessante... Dá pra fazer isso sim, mas em relação ao esquema de banco de dados que está usando... Você pode criar um esquema apenas para guardar suas tabelas e informá-lo na propriedade "org.hibernate.envers.default_schema" do persistence.xml e lá serão criadas as tabelas de auditoria...
ExcluirDá uma olhada: http://docs.jboss.org/hibernate/core/4.1/devguide/en-US/html/ch15.html
P.S: Ótimo post! o/
Meu projeto me retorna pagina 404 e esse erro
ResponderExcluirGRAVE: Exception sending context initialized event to listener instance of class org.springframework.web.context.ContextLoaderListener
Poderia me ajudar?