Injecting EntityManager Vs. EntityManagerFactory
A long question, please bear with me.
We are using Spring+JPA for a web application. My team is debating over injecting EntityManagerFactory
in the GenericDAO
(a DAO based on Generics something on the lines provided by APPFUSE, we do not use JpaDaosupport
for some reason) over injecting an EntityManager
. We are using "application managed persistence".
The arguments against injecting a EntityManagerFactory
is that its too heavy and so is not required, the EntityManager
does what we need. Also, as Spring would create a new instance of a DAO for every web request(I doubt this) there are not going to be any concurrency issues as in the same EntityManager
instance is shared by two threads.
The argument for injecting EFM is that its a good practice over all its always good to have a handle to a factory.
I am not sure which is the best approach, can someone please enlighten me?
The pros and cons of injecting EntityManagerFactory vs EntityManager are all spelled out in the Spring docs here, I'm not sure if I can improve on that.
Saying that, there are some points in your question that should be cleared up.
...Spring would create a new instance of a DAO for every web request...
This is not correct. If your DAO is a Spring bean, then it's a singleton, unless you configure it otherwise via the scope
attribute in the bean definition. Instantiating a DAO for every request would be crazy.
The argument for injecting EMF is that its a good practice over all its always good to have a handle to a factory.
This argument doesn't really hold water. General good practice says that an object should be injected with the minimum collaborators it needs to do its job.
I am putting down what I have finally gathered. From the section "Implementing DAOs based on plain JPA" in the Spring Reference:
Although EntityManagerFactory instances are thread-safe, EntityManager instances are not. The injected JPA EntityManager behaves like an EntityManager fetched from an application server's JNDI environment, as defined by the JPA specification. It delegates all calls to the current transactional EntityManager, if any; otherwise, it falls back to a newly created EntityManager per operation, in effect making its usage thread-safe.
This means as per JPA specifications EntityManager instances are not thread safe, but if Spring handles them, they are made thread safe.
If you are using Spring, it is better to inject EntityManagers instead of EntityManagerFactory.
I think this has already been well covered, but just to reinforce a few points.
The DAO, if injected by Spring, is a singleton by default. You have to explicitly set the scope to prototype to create a new instance every time.
The entity manger injected by @PersistenceContext is thread safe.
That being said, I did have some issues on with a singleton DAO in my multi-threaded application. I ended up making the DAO a instanced bean and that solved the problem. So while the documentation may say one thing, you probably want to test your application thoroughly.
Follow-up:
I think part of my problem is I am using
@PersistenceContext(unitName = "unit",
type = PersistenceContextType.EXTENDED)
If you use PersistenceContextType.EXTENDED, keep in mind you have to, if I understand correctly, manually close the transaction. See this thread for more information.
Another Follow-up:
Using an instanced DAO is an extremely bad idea. Each instance of the DAO will have its own persistence cache and changes to one cache will not be recognized by other DAO beans. Sorry for the bad advice.