JPA中的事务实现



我试图了解JPA中的事务是什么。

假设我有一个应用程序部署到带有持久性的glassfish:

<?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>

我正在尝试调试代码嗅探请求MySQL服务器:

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;

为什么? !为什么JPA的行为如此奇怪?

我期望在每个transaction.commit()调用上提交还是我误解了什么?

我在你的代码中看到一个问题:你将PersistenceContext定义为JTA,但使用RESOURCE_LOCAL事务API(即EntityManager.getTransaction())。

当您处于Java EE环境中时,只需获得UserTransaction: @Resource private UserTransaction transaction;EntityManager的注入实例,而不是创建一个。此外,您应该禁用CMT(容器管理)事务,否则它们将自动打开/关闭。

最新更新