EntityManager不需要的后台提交

时间:2012-08-30 09:53:51

标签: java jpa transactions glassfish

我的一个glassfish服务器上有一个奇怪的问题。看看这段代码:

userTransaction.begin();

MyEntity entity = new MyEntity(12345);
//setting values..
entityManager.persist(entity);

MyEntity persistedEntity = entityManager.createQuery("SELECT p FROM MyEntity p WHERE p.idpk=12345").getSingleResult();
//...

userTransaction.commit(); //OK => the tuple is in the DB

现在存在业务问题,需要回滚事务。

userTransaction.begin();

MyEntity entity = new MyEntity(12345);
//setting values..
entityManager.persist(entity);

MyEntity persistedEntity = entityManager.createQuery("SELECT p FROM MyEntity p WHERE p.idpk=12345").getSingleResult();
//...

//Business problem => rollback
userTransaction.rollback(); //ERROR => the tuple 12345 is in the DB !

即使回滚似乎工作(没有异常引发或奇怪的日志输出),元组已在数据库中提交... 要搜索问题所在,我尝试了以下代码:

userTransaction.begin();

MyEntity entity = new MyEntity(12345);
//setting values..
entityManager.persist(entity);

//Business problem => rollback
userTransaction.rollback(); //OK => the tuple 12345 is NOT in the DB !

使用此代码(未检索实体),元组未提交到数据库,这是正确的行为。让我们走得更远:

userTransaction.begin();

MyEntity entity = new MyEntity(12345);
//setting values..
entityManager.persist(entity);

MyEntity persisted = entityManager.find(MyEntity.class, 12345);
//...

//Business problem => rollback
userTransaction.rollback(); //OK => the tuple 12345 is NOT in DB

在最后一种情况下,结果仍然正确,并且没有提交给数据库的元组。在使用查询检索实体时,似乎EntityManager进行了一次神奇的[不需要的]提交...... 我还试图在另一个表上进行查询,这不会导致错误的提交(回滚工作)。此外,我试图在我自己的服务器上重现问题,并且没有问题:所有回滚都能正常工作。因此,它应该是服务器配置问题。

有关信息,它是在linux上运行的glassfish v2.1.1。 EntityManager位于FlushModeType.AUTO。

有没有人有想法?

谢谢&最好的问候!

3 个答案:

答案 0 :(得分:2)

找到一些讨论,似乎可以解释你所看到的一些内容:

通过EJB3的P-331在行动书中:

  

默认情况下,数据库刷新模式设置为AUTO。这意味着   Entity-Manager根据需要自动执行刷新操作。   通常,这发生在交易结束时   事务范围的EntityManagers以及持久化上下文   已关闭,适用于应用程序管理或扩展的EntityManagers。的在   此外,如果在查询中使用具有挂起更改的实体,则   持久性提供程序将在之前刷新对数据库的更改   执行查询。 如果刷新模式设置为COMMIT,则   持久性提供程序只会在与数据库同步时   事务提交。但是,你应该小心这一点   将您的责任与实体状态同步   数据库在执行查询之前。如果你不这样做而且   EntityManager查询返回数据库中的陈旧实体   应用程序可以处于不一致的状态。

P-353 EJB3在Action Book中说明:

  

如果查询设置为FlushModeType.COMMIT ,则更新的效果   对持久化上下文中的实体所做的不是由   规范,实际行为是特定于实现的。

也许尝试在

返回的查询上切换刷新模式

entityManager.createQuery("SELECT p FROM MyEntity p WHERE p.idpk=12345").getSingleResult();

或在实体经理本身,看看是否有任何改变?

这里有一些进一步的讨论:

http://www.coderanch.com/t/475041/ORM/databases/EntityManager-setFlushMode-COMMIT-Vs-Query

答案 1 :(得分:0)

为什么不这样做:

MyEntity persisted = entityManager.persist(entity);

答案 2 :(得分:0)

我终于找到了问题所在:在JDBC连接池中,有一个“事务”部分,其中启用了“非事务连接”选项...只需删除此选项就可以完成所有工作:)