@Autowired vs @PersistenceContext for EntityManager bean
SpringJpaEntitymanagerSpring Problem Overview
What is the difference between:
@Autowired
private EntityManager em;
versus:
@PersistenceContext
private EntityManager em;
Both options work in my application, but can I break something by using the @Autowired
annotation?
Spring Solutions
Solution 1 - Spring
You shouldn't use @Autowired
.
@PersistenceContext
takes care to create a unique EntityManager for every thread. In a production application you can have multiple clients calling your application in the same time. For each call, the application creates a thread. Each thread should use its own EntityManager. Imagine what would happen if they share the same EntityManager: different users would access the same entities.
usually the EntityManager or Session are bound to the thread (implemented as a ThreadLocal variable).
Source: https://stackoverflow.com/a/42074452/2623162
EntityManager instances are not thread-safe.
Source: https://docs.oracle.com/cd/E19798-01/821-1841/bnbqy/index.html
Please notice that @PersistenceContext
annotation comes from javax.persistence
package, not from spring framework. In JavaEE it is used by the JavaEE container (aka the application server) to inject the EntityManager. Spring borrowed the PersistenceContext annotation to do the same: to inject an application-managed (= not container-managed) EntityManager bean per thread, exactly as the JavaEE container does.
Solution 2 - Spring
@PersistenceContext
allows you to specify which persistence unit you want to use. Your project might have multiple data sources connected to different DBs and @PersistenceContext
allows you to say which one you want to operate on
check the explanation here: http://www.coderanch.com/t/481448/java-EJB-SCBCD/certification/unitName-PersistenceContext
Solution 3 - Spring
@PersistenceContext:
does not return entity manager instance
it returns container-managed proxy that acquires and releases presistence context on behalf of the application code
Solution 4 - Spring
@PersistenceContext
is a JPA standard annotation designed for that specific purpose. Whereas @Autowired
is used for any dependency injection in Spring. Using @PersistenceContext
gives you greater control over your context as it provides you with ability to specify optional elements e.g. name, properties
Solution 5 - Spring
You can create the following FactoryBean
to make EntityManager
properly injectable, even via constructor injection:
/**
* Makes the {@link EntityManager} injectable via <i>@Autowired</i>,
* so it can be injected with constructor injection too.
* (<i>@PersistenceContext</i> cannot be used for constructor injection.)
*/
public static class EntityManagerInjectionFactory extends AbstractFactoryBean<EntityManager> {
@PersistenceContext
private EntityManager entityManager;
@Override
public Class<?> getObjectType() {
return EntityManager.class;
}
@Override
protected EntityManager createInstance() {
return entityManager;
}
}
Please note, that because we use the @PersistenceContext
annotation internally, the returned EntityManager
will be a proper thread-safe proxy, as it would have been injected directly at the place of usage with field injection (using @PersistenceContext
).