Oliver Drotbohm opened SPR-10443 and commented

Currently you can inject any Spring bean into clients through constructor injection. A JPA EntityManager is an exception to that. Constructor injection has the benefit of being able to design classes in an immutable way. Also, you communicate required dependencies through it easily. Sadly, @PersistenceContext cannot be used on a constructor parameter and this probably won't change befor JPA 2.2 (giving 2.1 is close to final).

It would be cool to simply be able to inject EntityManager instances through either @Autowired or @Inject.


Issue Links: - DATAJPA-445 Enable support to inject EntityManager via constructor

12 votes, 17 watchers

Comment From: spring-projects-issues

Oliver Drotbohm commented

Created a ticket in Spring Data JPA to locally implement the support in there as it should be easy to add to the already registered bean definitions.

Comment From: spring-projects-issues

Oliver Drotbohm commented

We've implemented the support in Spring Data JPA and it seems generally useable even in a non Spring Data context. Activation of annotation based configuration could register the BeanFactoryPostProcessor as well.

Comment From: spring-projects-issues

Marcel Overdijk commented

To bad this is not possible yet. Especially in the light of http://olivergierke.de/2013/11/why-field-injection-is-evil/

Comment From: spring-projects-issues

Oliver Drotbohm commented

Marcel Overdijk – Care to elaborate why the Spring Data JPA support for that is insufficient?

Comment From: spring-projects-issues

Marcel Overdijk commented

Oliver Drotbohm I have a project not using Spring Data. In a earlier post you mentioned support in Spring Data JPA which seems generally usable even in a non Spring Data context. What do you mean exactly with that?

Comment From: spring-projects-issues

Francisco Lozano commented

I also want to use constructor-injection of EntityManager without Spring Data JPA, feels weird that field injection is forced here. An @Autowired constructor should work... 

Comment From: lucasoares

Will this be fixed anytime soon?

Comment From: jhoeller

For the time being, a plain Spring application can define a bean of type org.springframework.orm.jpa.support.SharedEntityManagerBean, wiring it to a specific EntityManagerFactory, potentially defining a qualifier on it (e.g. the persistence unit name) - and then injecting it via @Autowired and the common qualifier mechanism if necessary, or simply through a plain constructor argument.

Due to the separate nature of the shared EntityManager instance, there is no first-class mechanism to do so implicitly. An explicit SharedEntityManagerBean is a straightforward FactoryBean matched by type and does not require additional post-processors. Alternatively, you could declare an @Bean method which returns an EntityManager built through SharedEntityManagerCreator.createSharedEntityManager, not even involving a FactoryBean then:

@Bean
public EntityManager sharedEntityManager(EntityManagerFactory emf) {
    return SharedEntityManagerCreator.createSharedEntityManager(emf);
}

That's essentially what Spring Data JPA's post-processor ends up registering as well. If there is nothing else we can do at the core Spring Framework level, maybe we should explicitly show the approach above in the reference documentation.