在JBOSS 7.1 AS中,我使用容器管理的事务。对于每个请求,我会进行多次实体更新。大多数实体使用"插入,合并,刷新" EntityManager中的方法来管理更新。但是,有一个实体使用显式查询来执行" executeUpdate"在DB上(参见下面的代码片段)。此sql更新立即提交到数据库,并且未与容器管理事务(与其他实体更新一样)对齐。反正是否将显式的sql update(下面的那个)与container-managed-transaction对齐?我试图让回滚工作,这个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();
答案 0 :(得分:0)
在ut.commit之前,executeUpdate命令被提交到DB 执行
它可能已经刷新了数据库中的更改,但没有像在BMT中那样提交。
您可以尝试回滚&验证它是否真的提交了&在交易中。
以下仅提交ResetValue
的更改
执行本机或JPQL / HQL查询时,它会直接对数据库进行更改。 EntityManager可能不知道这些更改。
因此,管理实体不会被EntityManager& amp;隐式刷新。可能包含过时/陈旧的数据。
您可以查看文档以获取更多详细信息,以下是exerpt。
JPQL UPDATE查询提供了更新实体的替代方法 对象。与SELECT查询不同,SELECT查询用于从中检索数据 数据库,UPDATE查询不从数据库中检索数据, 但在执行时,更新指定实体对象的内容 数据库。
使用UPDATE查询更新数据库中的实体对象可能是 比检索实体对象稍微高效一点 更新它们,但应谨慎使用,因为绕过了 EntityManager可能会中断与数据库的同步。对于 例如,EntityManager可能不知道缓存的实体 UPDATE修改了持久化上下文中的对象 查询。因此,使用单独的是一个好习惯 EntityManager for UPDATE查询。