Use of joinTransaction in JPA
First, a few words of theory...
An application-managed entity manager participates in a JTA transaction in one of two ways.
- If the persistence context is created inside the transaction, the persistence provider will automatically synchronize the persistence context with the transaction.
- If the persistence context was created earlier (outside of a transaction or in a transaction that has since ended), the persistence context can be manually synchronized with the transaction by calling
joinTransaction()
on theEntityManager
interface. Once synchronized, the persistence context will automatically be flushed when the transaction commits.
After reading the above definition a few questions may arise:
how do we know that
ShoppingCartImpl
participates in JTA transaction ?
Because the class has been annotated with@Stateful
(or@Stateless
) annotation so the intention is to execute the class within Java EE environment which by default uses JTA transactions. A class doesn't need such annotation, if it will be executed in Java SE environment.how do we know application-managed entity manager is used in this particular case?
Because we are using@PersistenceUnit
annotation to injectEntityManagerFactory
and then manually creating and destroyingEntityManager
. By doing this we are telling Java EE container that we don't want our transaction to be automatically managed (like in case of transaction-scoped entity manager or extended entity manager types).why
em.joinTransaction()
is required increateLineItem
method?
By callingem.joinTransaction()
we notify the application-managed persistence context that it should synchronize itself with the current JTA transaction. Without such call the changes toOrder
would not be flushed to the underlying database when the transaction commits (at the end ofcreateLineItem
method).
NOTE: sinceEntityManagerFactory
instances are thread-safe andEntityManager
instances are not, an application must not callem.joinTransaction()
on the same entity manager in multiple concurrent transactions.
Sameer Sarmah
Updated on June 25, 2022Comments
-
Sameer Sarmah almost 2 years
The following code is from
JPA
specs. I could not understand whyem.joinTransaction()
is required increateLineItem(int quantity)
.Can anyone provide an apt explanation?
@Stateful public class ShoppingCartImpl implements ShoppingCart { @PersistenceUnit private EntityManagerFactory emf; private EntityManager em; private Order order; private Product product; @PostConstruct public void init() { em = emf.createEntityManager(); } public void initOrder(Long id) { order = em.find(Order.class, id); } public void initProduct(String name) { product = (Product) em .createQuery("select p from Product p where p.name = :name") .setParameter("name", name).getSingleResult(); } public LineItem createLineItem(int quantity) { em.joinTransaction(); LineItem li = new LineItem(order, product, quantity); order.getLineItems().add(li); em.persist(li); return li; } @Remove public void destroy() { em.close(); } }
-
JAVA about 5 yearsplease explain an application must not call em.joinTransaction() on the same entity manager in multiple concurrent transactions a little briefly like what happens with an scenario.