1

I'm using spring boot and i want to integrate spring with hibernate. I want to make a Session Factory bean for further using. But I can't autowire EntityManagerFactory, I can't autowire it only in the configuration class, in other classes it works. Can you help, please?

Configuration class

package kz.training.springrest.configuration;

@Configuration
@EnableTransactionManagement
public class DatabaseConfiguration {

    @Autowired
    private EntityManagerFactory entityManagerFactory;

    @Bean
    public SessionFactory getSessionFactory() {
        if (entityManagerFactory.unwrap(SessionFactory.class) == null) {
            throw new NullPointerException("factory is not a hibernate factory");
        }
        return entityManagerFactory.unwrap(SessionFactory.class);
    }
}

dependencies

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jpa</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-security</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>

        <dependency>
            <groupId>org.postgresql</groupId>
            <artifactId>postgresql</artifactId>
            <version>42.2.2</version>
        </dependency
    </dependencies>
Daimon
  • 345
  • 1
  • 5
  • 21
  • A few items: First, `EntityManagerFactory` is specially injected with `@PersistenceUnit`. Second, *why* are you wanting to do this manually when the standard Hibernate interface is now JPA? Last, even if you got the code shown working, you'd essentially be wiping out Spring's thread-tracked `EntityManager` handling. – chrylis -cautiouslyoptimistic- Jun 01 '18 at 12:48

2 Answers2

3

When you say

But I can't autowire EntityManagerFactory

does it fail to compile or throw an exception at run-time? If the latter, what does the stack-trace say?

One possible solution/work around might be to inject an em into the configuration instead of the em factory, using the @PersistenceContext annotation:

@Configuration
@EnableTransactionManagement
public class DatabaseConfiguration {

    @PersistenceContext
    private EntityManager entityManager;

    @Bean
    public SessionFactory getSessionFactory() {
        // no need to check for null here because if the unwrap fails, it will do
        // so by throwing a PersistenceException rather than returning null.
        return entityManager.unwrap( Session.class ).getFactory();
    }
}
Naros
  • 19,928
  • 3
  • 41
  • 71
Chris
  • 409
  • 3
  • 17
  • 1
    It fail to compile. I tried your variant but get next error org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'databaseConfiguration': Injection of persistence dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'getSessionFactory' – Daimon Jun 01 '18 at 16:20
0

I'm not exactly sure why you want to expose both beans because as @chrylis points out, you can easily unwrap the EMF into a SF where needed.

// Some spring component
@Component
public class MyFancyComponent {
  @PersistenceContext
  private EntityManager entityManager;

  public void doSomethingFancy() {
    // public SessionFactory API
    final SessionFactory sf = entityManager
         .unwrap( Session.class ).getFactory();

    // public SessionFactoryImplementor SPI
    final SessionFactoryImplementor sfi = entityManager
         .unwrap( SessionImplementor.class ).getFactory();
  }
}
Naros
  • 19,928
  • 3
  • 41
  • 71