118

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?

Arto Bendiken
  • 2,567
  • 1
  • 24
  • 28
Cosmin Vasii
  • 1,429
  • 3
  • 14
  • 18

6 Answers6

65

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.

Alex
  • 1,066
  • 2
  • 9
  • 15
  • 1
    I can confirm this when talking about threads. For example, without @PersistenceContext my application runs SQL insert/update in other thread but no changes are made to the database. – Adam Ostrožlík May 22 '20 at 07:52
42

@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

Manos Nikolaidis
  • 21,608
  • 12
  • 74
  • 82
sashok_bg
  • 2,436
  • 1
  • 22
  • 33
32

@PersistenceContext:

does not return entity manager instance

it returns container-managed proxy that acquires and releases presistence context on behalf of the application code

MagGGG
  • 19,198
  • 2
  • 29
  • 30
17

@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

Alex
  • 5,364
  • 9
  • 54
  • 69
  • 1
    I know this, but what is the impact in the application? Consider using the standard **@Transactional** from Spring. When using the **@Autowired**, the same behaviour as using **@PersistenceContext** will occur and have the em per application transaction? – Cosmin Vasii Jul 10 '15 at 07:58
  • 5
    I believe it is typically best practice to use `@PersistenceContext` as it more closely describes the type of dependency injection you are trying to achieve. In addition it provides optional parameters specifically for the use of a EntityManager, this can be useful when you have more than one EntityManager. Functionally I believe you could achieve the same injection with `@Autowired`, but I would recommened using the annotation designed to be used like this. – Alex Jul 10 '15 at 08:15
1

I think @Autowire will work same way as @PersistenceContext

https://docs.spring.io/spring-data/jpa/docs/current/reference/html/#jpa.misc.jpa-context

When working with multiple EntityManager instances and custom repository implementations, you need to wire the correct EntityManager into the repository implementation class. You can do so by explicitly naming the EntityManager in the @PersistenceContext annotation or, if the EntityManager is @Autowired, by using @Qualifier.

As of Spring Data JPA 1.9, Spring Data JPA includes a class called JpaContext that lets you obtain the EntityManager by managed domain class, assuming it is managed by only one of the EntityManager instances in the application. The following example shows how to use JpaContext in a custom repository:

Vahe Harutyunyan
  • 652
  • 2
  • 10
  • 17
-1

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).

mihu86
  • 969
  • 8
  • 9