10

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?

ashishjmeshram
  • 12,095
  • 56
  • 156
  • 228

4 Answers4

8

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.

deniss-s
  • 167
  • 1
  • 6
4

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());
}
Jay
  • 3,094
  • 2
  • 23
  • 29
2

AuditReaderFactory only has two static methods. Can you autowire a SessionFactory object or your EntityMananger? Looks like either would give you what you want, which is access to an AuditReader.

AuditReaderFactory.get(sessionFactory.getCurrentSession())

EDIT this post has some detail or wiring SessionFactory if needed

Community
  • 1
  • 1
heisbrandon
  • 1,140
  • 7
  • 7
  • Following linked, to autowire SessionFactory, this didn't work; Can create and save entities, still can't get AuditReaderFactory: (spring 1.5, hibernate 5.2.1) org.hibernate.HibernateException: No CurrentSessionContext configured! – Jay Jun 05 '18 at 16:45
1

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();
         ...
    }

}

Giulio Pulina
  • 176
  • 1
  • 13