This summarizes what I learnt from the Java EE tutorial, and the following articles
http://www.kumaranuj.com/2013/06/jpa-2-entitymanagers-transactions-and.html
this is one with VERY GOOD examples / error examples
http://piotrnowicki.com/2012/11/types-of-entitymanagers-application-managed-entitymanager/
EntityManager - manages persistent state of an entity
always manages one persistence context
Persistence Unit - named configuration of entity classes
Persistence Context -
managed set of entity instances
the entities classes are part of the Persistence Unit configuration
"understands persistence context, understands Entity Manager"
Managed Entities - an entity instance is managed if it's part of a persistence context and that Entity Manager can act upon it
Working with MySQL and Wildfly 10. No provider (so uses server default) but at least specify dialect. "creat-drop" is for development environment only!
<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.1" xmlns="http://xmlns.jcp.org/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence http://xmlns.jcp.org/xml/ns/persistence/persistence_2_1.xsd">
<persistence-unit name="V8MbArea">
<jta-data-source>java:/cnipdb</jta-data-source>
<properties>
<property name="hibernate.dialect" value="org.hibernate.dialect.MySQL5InnoDBDialect"/>
<property name="hibernate.hbm2ddl.auto" value="create-drop"/>
</properties>
</persistence-unit>
</persistence>
Summary of types of Entity Manager:
container / application managed:
container manages transaction (with annotation), or
application manages transaction with calls to user transaction
depends on how EM is obtained
Extended / transaction scoped:
extended: transaction is allowed to span beyond single method, or
transactional: one method = one transaction
depends on when EM is obtained (type=...) in annotation
JTA / resource-local transaction (how to implement the commit)
JTA: JTA manages EM's transactions (behind the scene may involve multiple data sources)
CMT (container managed JTA transactions)
use javax.ejb.TransactionAttribute to define transaction behaviour (annotation)
BMT (bean managed JTA transactions)
use javax.transaction.UserTransaction
Resource-local: use EM's direct API to begin and commit (behind the scene JDBC connection)
depends on attribute in persistence.xml
transaction object must be obtained accordingly (UserTransaction or EntityTransaction)
In combination:
container-managed
extended or transactional scoped
always JTA transaction
application-managed
always extended scoped
JTA or Resource-local transaction
IMPORTANT:
EM only manages context, it may not have a transaction available, not jointed one, and end up seemingly works (without any exception) but not persisting anything!
Special note:
When first time creating / obtaining an Entity Manager, it's better not in a transaction (for example, a user transaction not started). Depends on configuration (hibernate <property name="hibernate.hbm2ddl.auto" value="create-drop" />) tables may be created / dropped. Hibernate implementation may throw an exception if in a transaction.
Container Managed Entity Managers (general)
EE container manages the life-cycle
the scope means scope of the Persistence Context, not the manager
automatically propagated with current transaction
in two flavors, depends on if the Entity Manager's operations might span across multiple transactions
Container Managed Transaction Scoped entity managers
most commonly used one
obtain - @PersistenceContext(unitName="xxx") EntityManager em;
one method call, one transaction
can be used by both stateful / stateless EJB
stateless MUST use (stateless cannot predict which client to serve in next call)
is Stateless, therefore Threadsafe, maintenance free
because it depends on JTA transactions, which holds Persistence Context
if JTA transaction does not exist, throw exception
if JTA transaction exists, and
has existing Persistence Context, use it
has no existing Persistence Context, creates one
when transaction is over, Persistence Context goes away
all changes flushed (if committed)
all managed entities detached
optimization tip for read-only query: @TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED)
Container Managed Extended Scoped entity managers
obtain: @PersistenceContext(unitName="xxx" , type=PersistenceContextType.EXTENDED)
can be used by stateful EJB only
transaction can extend beyond methods
if want the Persistence Context to be available beyond the scope of a method
to understand: the class needs to maintain some state (created as a result of some transactional request like find the entity and then use the entity) and share the state across business methods
not a generally good practice; it's usually wise to obtain instances, work on them, persist them at last
Persistence Context is
created at bean initialization time by container
available until bean removed from client, at which time the transaction is committed
the @Remove annotated method is called, or
EJBObject.remove()
generally NOT Threadsafe unless used inside a Stateful session bean for which container is responsible for making it thread safe
Again: inside JEE container, Extended Scoped Entity Managers should be used with @Stateful beans, otherwise no thread safety guaranteed and thread safety needs to be handled by self
Application Managed (extended scoped) Entity Managers
can use in Java SE
application manages life-cycle
every application-managed EM has the extended scope
wrong usage:
if not manually started transaction, changes may not be saved at all
can use user transaction started earlier
if created before user transaction starts, the EM is outside of transaction and changes will not be saved
if created before user transaction starts, call EntityManager.joinTransaction() to join outside transaction
to obtain, see below (another way is to pass a properties, not discussed)
have to manually obtain transaction and manually manage transaction demarcation
using JTA:
use UserTransaction utx;
utx.begin(); utx.commit(); utx.rollback();
to obtain UserTransaction
use JNDI lookup
use SessionContext.getUserTransaction()
use @Resource UserTransaction utx;
mind: in persistence.xml, <jta-data-source>
using resource local:
javax.persistence.EntityTransaction EntityManager.getTransaction()
EntityTransaction.begin(); commit(); rollback()
mind: in persistence.xml, <non-jta-data-source>
can span multiple JTA transactions
by calling em.joinTransaction()
make sure to close every time done with using it
container won't do it
every time obtaining, an EM is created that is connected to the NEW Persistence Context
@PersistenceUnit EntityManagerFactory emf;
EntityManager em = emf.createEntityManager();
// or....
EntityManagerFactory emf =
Persistence.createEntityManagerFactory("myPersistenceUnit");
EntityManager em = emf.createEntityManager();
Transactions are related to entities - managing transactions manages entity lifecycle
Persistence Context is managed set of entity instances
From end user perspective, the only role of EntityManager is
to determine the lifetime of Persistence Context and
plays NO ROLE in how Persistence Context should behave (such as, how to commit?)
when transaction begins Persistence Context associates with transaction, when transaction ends, Persistence Context flushed and get disassociated with transaction
Two types of transaction management types supported in JPA
RESOURCE LOCAL
native transactions of JDBC driver
a single transactional resource (e.g. a JDBC connection)
use javax.persistence.EntityTransaction EntityManager.getTransaction() to manage transactions
JTA or GLOBAL transaction
transactions of the JEE server
support multiple transactional resources
two types of JTA transactions management
CMT (container managed JTA transactions)
use javax.ejb.TransactionAttribute to define transaction behaviour (annotation)
BMT (bean managed JTA transactions)
use javax.transaction.UserTransaction
Container Managed Entity Managers always use JTA
Application Managed Entity Managers can use either
be defined in persistence.xml using "transaction-type" attribute
<persistence-unit transaction-type="RESOURCE_LOCAL" ... >
default is JTA
one Persistence Context can associate with One or More transactions, thus
one Persistence Context can associate with One or More Entity Managers
When transaction starts
entity manager looks for an active Persistence Context instance; may create one
Persistence Context gets registered with transaction
When transaction commits
Persistence Context flushes
Persistence Context get dissociated with transaction
Sometimes needs transaction propagation - sharing a single persistence context between different Entity Managers within a single transaction (in container managed, transaction scoped EMs)
Transaction Scoped Persistence Context example: 1st bean is injected @PersistenceContext em (CM transaction scoped EM)
1st bean creates an entity, then calls the 2nd bean
2nd bean is injected @PersistenceContext em, gets a different entity manager instance
2nd bean entity manager finds the existing persistence context and associates itself with the context (propagation)
2nd bean can find the newly created entity by id in the persistence context even transaction has not committed and entity has not been saved in database
Persistence Context scopes (note the scope of EntityManager instance):
Transaction Scoped Persistence Context
created by entity manager only when needed (lazy creation) when a method in entity manager is called for the first time)
created one for every transaction (in case non-propagation)
Extended Scoped Persistence Context
created once (eager creation) and used by all the transactions within the scope of the class that manages the lifecycle of the Extended Persistence Context
in Jave EE, Stateful session bean manages lifecycle of the extended Persistence context
relationship with Transaction / Extended scoped EntityManager:
transaction scoped entity manager creates transaction scoped persistence context
extended scoped entity manager uses extended persistence context
If want to share EntityManager between components that constitutes one transaction, can pass it manually.
Can produce Request Scoped EntityManager and inject into components.
Share Application-managed Entity Manager
public class Resources {
@PersistenceUnit
EntityManagerFactory emf;
@Produces @RequestScoped
public EntityManager createEntityManager() {
return emf.createEntityManager();
}
}
Note: if the EM is injected in a non-transactional bean (@TransactionAttribute), it is ended up without transaction and will not persist anything! (this is application managed entity manager!)
CDI does not know about running transaction and just share the instance.
That's the difference between @Inject and @PersistenceContext, etc.
Share Container-managed Entity Manager
@Produces @PersistenceContext EntityManager em
Then uses @Inject EntityManager.
This would work exactly as @PersistenceContext EntityManager but allow to define the entity manager (like name of persistence unit) in a single place