envers
TRANSCRIPT
HIBERNATEENVERS
SOLUÇÃO PARA AUDITORIA DE OBJETOS PERSISTENTES
terça-feira, 21 de fevereiro de 12
AGENDA• INTRODUÇÃO
• ESTRUTURA
• POR QUE ARMAZENAR RASTRO ?
• EXEMPLO BÁSICO
• NECESSIDADE ATUAL (SPO)
terça-feira, 21 de fevereiro de 12
INTRODUÇÃO
• O QUE É O ENVERS
• COMO SURGIU
• COMO ELE ESTÁ
• COMO ELE PODE NOS AJUDAR
terça-feira, 21 de fevereiro de 12
POR ARMAZENAR RASTRO?
terça-feira, 21 de fevereiro de 12
O PROBLEMA
• Armazenar log em um ambiente distribuído e centrlizado
terça-feira, 21 de fevereiro de 12
CAUSAS
• Latência extrema na execução de transações.
• Marshall e Unmarshall de objetos
terça-feira, 21 de fevereiro de 12
SOLUÇÕES
• ????????????????
terça-feira, 21 de fevereiro de 12
O BÁSICOPOREM, FUNCIONAL
terça-feira, 21 de fevereiro de 12
MODELO ESTRUTURAL
ENVERS
ANNOTATION@Audited
@RevisionEntityRevisionListener
terça-feira, 21 de fevereiro de 12
EXEMPLOS
terça-feira, 21 de fevereiro de 12
EXEMPLOS@Entity@Table(name = "ecm_address") //renomeado para suportar a mudanca no ER@AttributeOverride(name = "id", column = @Column(name = "addressId"))@Auditedpublic class Address extends AbstractEntity {
private String rua; private String bairro; private String CEP; private String complemento; private String pontoReferencia; private Boolean entrega;
@Entity@RevisionEntity(EnversRevisionListener.class)@Table(name = "ecm_login_rev_entity") public class LoginRevEntity { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) @RevisionNumber private Long id; private String usuario; @RevisionTimestamp private long timestamp;
public class EnversRevisionListener implements RevisionListener {
@Override public void newRevision(Object revisionEntity) { Map<String,Object> session = ActionContext.getContext().getSession(); if(session != null) { ApplicationUserElementSession userSession = (ApplicationUserElementSession) session.get(Constants.APPLICATION_USER_SESSION); LoginRevEntity exampleRevEntity = (LoginRevEntity) revisionEntity; exampleRevEntity.setTimestamp(new Date().getTime()); if(userSession != null) { User userAutenticated = userSession.getUserAutenticate(); exampleRevEntity.setUsuario(userAutenticated.getLogin()); } else { exampleRevEntity.setUsuario("new_user"); } } }}
terça-feira, 21 de fevereiro de 12
CONSULTASCONCEITO DE REVISÕES
terça-feira, 21 de fevereiro de 12
CONSULTAS• Entidades em revisão
• Revisões sobre entidades
• Elementos inspirados por consultas com estilos Criteria
• Impossibilidade de realizar consultas com recursos JPA
• Conhecendo o modelo, podemos utilizar SQL para gerar relatórios
auditReader.createQuery() .forRevisionsOfEntity(Person.class, false, true) .addProjection(AuditEntity.revisionNumber().count()) .add(AuditEntity.id().eq(person.getId())) .getSingleResult()
terça-feira, 21 de fevereiro de 12
NAPRÁTICA
terça-feira, 21 de fevereiro de 12
DESEMPENHO
www.devoxx.com42
Must be slower than without auditing:
1 insert for each modified entity
1 insert for each transaction
Performance
MySQL 5.1.30
(InnoDB)
5000
inserts
1000
complex inserts
5000
updates
Not audited
Audited
Difference
6.307s 6.622s 8.487s
9.807s 12.758s 11.444s
x 1.55 x 1.92 x 1.34
42
• Um INSERT para cada entidade modificada
• Um INSERT para cara transação
terça-feira, 21 de fevereiro de 12
COMO FICARIA NO SPO ??
- Interface de administração* Propriedades do sistema* Dados de auditoria
terça-feira, 21 de fevereiro de 12
CONCLUSÕES
• SOLUÇÕES DE AUDITORIA EM BASE DE DADOS LOCAIS
• + desempenho
• + flexibilidade
• + controle
• - XML/SOAP
terça-feira, 21 de fevereiro de 12
REFERÊNCIAS
• JBoss Comunity - Envers Documentation: http://www.jboss.org/envers
• Adam Warski Blog - Criador do Envers: http://www.warski.org/blog/
• Textos explicativos: www.nelsonalone.com.br
terça-feira, 21 de fevereiro de 12