Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

CDI Transaction Management: How does @Transactional work?

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?

like image 568
John Rumpel Avatar asked Oct 25 '25 14:10

John Rumpel


1 Answers

@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.

like image 122
Harald Wellmann Avatar answered Oct 28 '25 04:10

Harald Wellmann