JPA specification defines two ways of how to configure and use it:
With the Application-managed Persistence Context approach, the application code directly creates EntityManager
using EntityManagerFactory
. With the Container-managed Persistence Context, the container is responsible for this.
Seems this is all related only to controlling of EntityManager
instances (create, destroy, etc).
The question is. Why do we have two different methods in the PersistenceProvider
class? (I mean with different parameters)
I mean these:
public EntityManagerFactory createEntityManagerFactory(String emName, Map map)
public EntityManagerFactory createContainerEntityManagerFactory(PersistenceUnitInfo info, Map map)
The first one seems for the Application managed type. And it works only with the persistence.xml
file because it can take only the name of the persistence unit. The second is for Container managed type. And it can take the PersistenceUnitInfo
object. Why I cannot use the Application Managed type with the custom PersistenceUnitInfo parameter? It seems both variants work with containers anyway. The difference occurs only in controlling EntityManager
instances. When we are talking about the configuration of EntityManagerFactory
, this object always resides inside a container, because I can inject it with the @PersistenceUnit
annotation.
This seems strange, as I still can specify the data source for the Application managed type with the <jta-data-source>
tag. And I can do the same with Container managed type using the java setter method. If I can do the same things, why I am limited with only XML tag in one variant and I can use java setter (java configuration) in the second?
So the "container" here in this terminology refers to a Java EE / Jakarta EE container (aka an "application server"). I think the reason this probably seems so confusing is because most documentation is geared towards the typical application developer, but you're asking about code that's typically the responsibility of the JPA provider and the container provider.
In the most typical cases, an application running in a Java EE / Jakarta EE container would not use these PersistenceProvider
methods. It might inject an EntityManager
(container-managed persistence context) or inject an EntityManagerFactory
(app-managed persistence context).
The PersistenceProvider#createContainerEntityManagerFactory(PersistenceUnitInfo info, Map map)
method is intended for a JPA provider to allow a Java EE / Jakarta EE Container to create an EMF which can probably be used for both container-managed and application-managed persistence contexts.
And in a Java SE environment, the application would call Persistence.createEntityManagerFactory(...)
which would find a Provider and call its PersistenceProvider#createEntityManagerFactory
method. Here too, the app wouldn't need to call PersistenceProvider
itself.
So if you have a typical app and you're trying to figure out what PersistenceProvider
method to call, then you probably are on the wrong track and should be starting from a better example.
This all works well and is handled for you, as described, when you're using the typical aproach of using the persistence.xml to load the persistence context. If your application wants to do something different and custom, however, then you get into the realm of maybe wanting to call the PersistenceProvider
yourself. E.g. this is one article that discusses the subject a bit. You may end up tying your application to a specific provider with this approach.
I'm not sure exactly what the specification says about this case, if anything. I would describe it as having more of an "app-managed persistence" feel since you're certainly creating EntityManager(s) yourself but I'm not sure if that's a correct or helpful description.