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