CDI Transaction Management: How does @Transactional work?
cdi, ejb, jakarta-ee, jpa, transactions
Solution
`@javax.transaction.Transactional` is an interceptor binding introduced in Java EE 7. The proxy injected by CDI for your bean will intercept annotated method calls to wrap them in a transaction.
Interceptors do not work for private methods - I suppose that's the main problem with your example.
Problem
Having a simple CDI bean in session scope with an entity manager injected: ``` @Named("myBean") @SessionScoped public class MyBean implements Serializable { private static final long serialVersionUID = 1L; @Inject EntityManager em; ... @Transactional private void testInsert() { long t = System.currentTimeMillis(); for (int i=1; i<50000; i++) { create(i); } System.out.println("Time: " + Long.toString(System.currentTimeMillis()-t)); } private void create(int i) { Project p = new Project("Project " + i); em.persist(p); } } ``` Now, when calling the function via EL #{myBean.testInsert} there are two things that seems to be very strange: 1) Moving the @Transactional-annotation to the method create(int) I get: javax.persistence.TransactionRequiredException: JBAS011469: Transaction is required to perform this operation (either use a transaction or extended persistence context) 2) Decorating testInsert() with @Transactional instead, the function returns instantly but JPA is still updating the database within a background thread. The process needs 2 minutes to finish INSERT of only 50000 records. When shutting down the Java EE-application server within the process, the background process stops and thus - in my opinion - testInsert() is not transactional. What is my general misunderstanding here? How to manage transactions properly?