1

I'm trying to understand what is transaction in JPA.

Say I have an application deployed to glassfish with persistence:

<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.0" xmlns="http://java.sun.com/xml/ns/persistence"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd">
  <persistence-unit name="survex" transaction-type="JTA">
    <jta-data-source>jdbc/MyDatabase</jta-data-source>
    <exclude-unlisted-classes>false</exclude-unlisted-classes>
    <properties>
    </properties>
  </persistence-unit>
</persistence>

I'm trying to debug code sniffering requests to MySQL server:

public String create() {

        EntityManagerFactory entityManagerFactory = Persistence.createEntityManagerFactory("survex");
        EntityManager em = entityManagerFactory.createEntityManager();
        Log log = em.find(Log.class, 1); 

        EntityTransaction transaction = em.getTransaction();
        transaction.begin(); // NOTING HAPPENS ...
        log.setMessage("xxx");  
        em.flush(); // OH, HERE IT IS -> SET autocommit=0; UPDATE LOG SET message = 'xxx' WHERE (id = 1)
        log.setMessage("aaa");
        em.flush(); // OK -> UPDATE LOG SET message = 'aaa' WHERE (id = 1)
        transaction.commit(); // NOTHING HAPPENS! WHERE IS COMMIT?!

        log = em.find(Log.class, 1);

        transaction = em.getTransaction();
        transaction.begin(); // STILL NOTHING ...
        log.setMessage("555"); 
        em.flush(); // UPDATE LOG SET message = '555' WHERE (id = 1)
        log.setMessage("666");
        em.flush(); // UPDATE LOG SET message = '666' WHERE (id = 1)
        transaction.commit(); // NOTHING!!!

        return log.getMessage();
    }
    // SOMEWHERE OUTSIDE: COMMIT; SET autocommit=1;

Why?! Why JPA behaves so strangely?

I expect commit on every transaction.commit() call or I'm misunderstanding something?

Ivan Nevostruev
  • 28,143
  • 8
  • 66
  • 82
corvax
  • 1,095
  • 1
  • 10
  • 35

1 Answers1

1

I see one problem in your code: you defined you PersistenceContext as being JTA, but work with the RESOURCE_LOCAL transaction API (i.e EntityManager.getTransaction()).

As you are in a Java EE environment, just get an injected instance of UserTransaction: @Resource private UserTransaction transaction; and of an EntityManager instead of creating one. Also you should disable the CMT (container managed) transactions, otherwise they are automatically opened/closed.

V G
  • 18,822
  • 6
  • 51
  • 89
  • I think you're right! Cause I get this exception: Unable to create EntityManager with SynchronizationType because PersistenceUnit is configured with resource-local transactions when trying to do this - entityManagerFactory.createEntityManager(SynchronizationType.SYNCHRONIZED); Can you provide a code sample of right usage? – corvax Mar 13 '14 at 22:08
  • 1
    Yes of course. But I propose you to read this very good article http://piotrnowicki.com/2012/11/types-of-entitymanagers-application-managed-entitymanager/ on the types of EntityManagers and decide yourself how to write the code. If you want to try it without reading, google for injecting EntityManager into a Servlet or an EJB, as it is a bit more to write. – V G Mar 14 '14 at 08:33