I am using spring boot and spring data jpa. I am also using hibernate envers and I need access to AuditReaderFactory so that I can write Audit Queries.
Since, its a spring boot and spring data jpa, everything is auto configured. So when I do this,
@Autowired
AuditReaderFactory auditReaderFactory;
It doesn't work. I get the following error.
org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [org.hibernate.envers.AuditReaderFactory] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency
How do I get a proper reference to AuditReaderFactory in my repository classes?
Enabling JPA Auditing. To start, we want to enable auditing via annotation configuration. In order to do that, we add @EnableJpaAuditing on our @Configuration class: @Configuration @EnableTransactionManagement @EnableJpaRepositories @EnableJpaAuditing public class PersistenceConfig { ... }
Spring Boot JPA Audit Logging Example Spring Data helps you keep track of who created or modified an entity, as well as when it happened. To leverage this auditing functionality, you must provide auditing metadata to your entity classes, which can be defined using annotations or by implementing an interface.
Create configuration class such as AuditConfiguration.java:
import org.hibernate.envers.AuditReader;
import org.hibernate.envers.AuditReaderFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import javax.persistence.EntityManagerFactory;
@Configuration
public class AuditConfiguration {
private final EntityManagerFactory entityManagerFactory;
AuditConfiguration(EntityManagerFactory entityManagerFactory) {
this.entityManagerFactory = entityManagerFactory;
}
@Bean
AuditReader auditReader() {
return AuditReaderFactory.get(entityManagerFactory.createEntityManager());
}
}
After that you can autowire AuditReader
in your component classes.
Following up on above answer, and linked question, I found this to work. (Would be nice if this can be turned into an autowire of the reader directly somehow)
@Autowired
private EntityManagerFactory factory;
public void stuff() {
AuditReader audit = AuditReaderFactory.get(factory.createEntityManager());
}
In my opinion, @deniss-s answer (top-voted one) is not correct because EntityManager must not be reused outside of the context of a transaction (see https://stackoverflow.com/a/9375891/554117), while the solution makes use of it as a singleton.
A correct retrieval of AuditReader looks like this:
public class AuditRepository {
@PersistenceContext
private EntityManager entityManager;
private AuditReader getAuditReader() {
return AuditReaderFactory.get(entityManager);
}
public Optional<T> getRevision() {
final AuditReader auditReader = getAuditReader();
...
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With