"id", column = @Column(name = "log_trace_id"))public class LogTrace extends BaseEntity { @Column(name = "transaction_type", nullable = false) @Enumerated(EnumType.STRING) private TransactionType transactionType; @Column(name = "entity_name", nullable = false) private String entityName; @Column(name = "registry_id", nullable = false) private Long registryId; @Column(name = "operation_date", nullable = false) @Temporal(TemporalType.TIMESTAMP) private Date operationDate; @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "executed_by", nullable = false) private User executedBy;...getters e setters...}3- Criar o repositorio (DAO) e o servico como esta sendo feito no restante do sistema;4- Criar o listener que sera disparado pelo hibernate:public class LogTraceListener { @Autowired LogTraceService logTraceService; @Autowired UserService userService; @PostRemove void postDelete(BaseEntity e) { createLog(TransactionType.DELETE, e); } @PostPersist void postPersist(BaseEntity e) { createLog(TransactionType.CREATE, e); } @PostUpdate void postUpdate(BaseEntity e) { createLog(TransactionType.UPDATE, e); } private void createLog(TransactionType transactionType, BaseEntity e) { /* * OBSERVACAO 1. */ if (logTraceService == null) { ApplicationContext ctx = ContextLoader.getCurrentWebApplicationContext(); logTraceService = (LogTraceService) ctx.getBean("logTraceService"); } /* * OBSERVACAO 2. */ User user = userService.getAuthenticatedUser(); LogTrace logTrace = new LogTrace(); /* * OBSERVACAO 3. */ String entityName = e.getClass().getAnnotation(Table.class).name(); if (entityName == null || entityName.isEmpty()) { entityName = e.getClass().getSimpleName(); } logTrace.setTransactionType(transactionType); logTrace.setEntityName(entityName); logTrace.setRegistryId(e.getId()); logTrace.setExecutedBy(user); logTrace.setOperationDate(new Date()); logTraceService.save(logTrace); }}Observacoes:1- O listener e disparado pelo mecanismo JPA. Uma vez que a classe nao foi instanciada pelo Spring, as dependencias nao sao injetadas e para resolver isso, podemos usar aspectos (AOP) ou uma abordagem mais simples como a feita acima;2- A logica de recuperacao do usuario logado (via consulta ou busca na sessao) esta no servico neste caso;3- Alguns projetos adotam o uso da anotacao @Table, neste listener, coloquei uma logica que abrange esta abordagem (como principal) e se nao for o caso, o campo recebera o nome da entidade, por exemplo, "PedidoInterno", ao inves de "pedido_interno" (que e a forma como os bancos normalmente sao modelados. Veja que nossa "LogTrace" teria o campo salvo como "log_trace";5- Anotar entidades que devem ser auditadas:As entidades que devem ser auditadas recebem a anotacao @EntityListeners(value = LogTraceListener.class). Para melhorar a leitura da classe, indico colocar esta anotacao logo apos a anotacao @Entity ou @Table(name = "minha_entidade").Com isso, sempre que uma das operacoes monitoradas pelo listener acontecer, sao as anotacoes que estao sobre os metodos: @PostPersist, @PostUpdate e @PostRemove, um registro sera gerado na tabela de log de auditoria.Para que outra tabela/entidade seja autitada, basta repetir o passo 5 (incluir a anotacao na entidade).NOTA: Normalmente as entidades de um sistema extendem uma entidade base ou implementam uma interface para que um padrao "minimo" seja seguido. Este exemplo foi construido considerando este caso, ou seja, as entidades extendem BaseEntity.