Jpa 在JTA事务中(使用容器管理的事务),显式查询的executeUpdate方法会立即提交

Jpa 在JTA事务中(使用容器管理的事务),显式查询的executeUpdate方法会立即提交,jpa,jboss7.x,entitymanager,ejb-3.1,jta,Jpa,Jboss7.x,Entitymanager,Ejb 3.1,Jta,在JBoss7.1AS中,我使用的是容器管理的事务。对于每个请求,我都会进行几个实体更新。大多数实体使用EntityManager中的插入、合并和刷新方法来管理更新。但是,有一个实体使用显式查询在DB上执行更新。代码段请参见下文。此sql更新将立即提交给DB,并且与其他实体更新一样,它与容器管理的事务不一致。下面的sql更新是否与容器管理的事务保持一致?我正在尝试回滚,但此sql更新没有回滚。除此之外,所有其他实体更新和插入都可以正常工作。谢谢你的帮助 代码段: entityManager.cr

在JBoss7.1AS中,我使用的是容器管理的事务。对于每个请求,我都会进行几个实体更新。大多数实体使用EntityManager中的插入、合并和刷新方法来管理更新。但是,有一个实体使用显式查询在DB上执行更新。代码段请参见下文。此sql更新将立即提交给DB,并且与其他实体更新一样,它与容器管理的事务不一致。下面的sql更新是否与容器管理的事务保持一致?我正在尝试回滚,但此sql更新没有回滚。除此之外,所有其他实体更新和插入都可以正常工作。谢谢你的帮助

代码段:

entityManager.createQuery 
 ( "UPDATE Balance a SET a.balanceValue = :newValue WHERE a.balanceId =:balanceId AND a.balanceValue = :currentValue" ) .setParameter("balanceId", cb.getBalanceId()) .setParameter("currentValue", cb.getBalanceValue()).setParameter("newValue", newAmt).executeUpdate();
附加代码:下面的代码使用Bean管理的事务,但我也得到了CMT的相同行为

            ut.begin();
        ChargingBalance bal2 = entityManager.find(ChargingBalance.class, 13);
        bal2.setResetValue((new Date()).getTime());
        String UPDATE_BALANCE_AND_EXPIRYDATE_EQUAL = "UPDATE ChargingBalanceValue a"
                + "  SET a.balanceValue = :newValue "
                + "  WHERE a.balanceId = :balanceId";

        Query query = entityManager.createQuery(UPDATE_BALANCE_AND_EXPIRYDATE_EQUAL)
                .setParameter("balanceId", 33)
                .setParameter("newValue", 1000l);

        /*The executeUpdate command gets committed to DB before ut.commit is executed */
        query.executeUpdate();

        /* This below only commits changes on ResetValue */
        ut.commit();

        ut.begin();
        ChargingBalance bal = entityManager.find(ChargingBalance.class, 23);
        bal.setResetValue(1011l);

        query = entityManager.createQuery(UPDATE_BALANCE_AND_EXPIRYDATE_EQUAL)
                .setParameter("balanceId", 33)
                .setParameter("newValue", 2000l);
        query.executeUpdate();

        /* This rollback doesn't rollback changes executed by executeUpdate, but it rollbacks ResetValue change */
        ut.rollback();
executeUpdate命令在执行ut.commit之前提交到DB 执行

它可能已将更改刷新到数据库中,但没有像在BMT中那样提交

您可以尝试回滚并验证它是否真的已提交以及是否在事务中

以下内容仅提交对ResetValue的更改

当您执行本机或JPQL/HQL查询时,它将直接对数据库进行更改&EntityManager可能不知道这些更改

因此,EntityManager不会隐式刷新托管实体&可能包含过时/过时的数据

您可以通过文档了解更多详细信息,下面是练习

JPQL更新查询提供了一种更新实体的替代方法 物体。与SELECT查询不同,SELECT查询用于从中检索数据 数据库、更新查询不从数据库检索数据, 但在执行时,更新中指定实体对象的内容 数据库

可能需要使用更新查询更新数据库中的实体对象 比检索实体对象然后 更新它们,但应谨慎使用,因为绕过 EntityManager可能会中断与数据库的同步。对于 例如,EntityManager可能不知道缓存的实体 对象在其持久性上下文中已被更新修改 查询因此,使用单独的 更新查询的EntityManager


尝试添加一些相关的代码,我做了几个实体更新。大多数实体使用insert、merge、refresh,因此不清楚如何更新实体&您如何得出大多数实体使用insert、merge、refresh等的结论。使用哪个JPA实现?我添加了一些附加代码。我正在使用JPA2.0的Hibernate实现。org.hibernate:hibernate entitymanager:4.2.7.sp1非常感谢您的帮助。我被这个问题困扰了一段时间。谢谢你的回复!我发现了这个问题。这与JBoss7.2问题有关,无法通过UI更新数据源页面上的JTA选项。我认为在persistence.xml上配置transaction type=JTA就足够了。然而,我错了。当我手动更新standalone.xml并重新启动JBOSS时。当CMT提交其余事务时,显式查询正在提交。s感谢您的帮助!