题 Hibernate事务未成功启动


考虑一下这个简单的Hibernate场景:

session = getHibernateSession();
tx = session.beginTransaction();
SomeObject o = (SomeObject) session.get(SomeObject.class, objectId);
tx.commit();

此代码生成以下异常:

org.hibernate.TransactionException: Transaction not successfully started
    at org.hibernate.transaction.JDBCTransaction.commit(JDBCTransaction.java:100)
    at com.bigco.package.Clazz.getSomeData(Clazz.java:1234)

这是怎么回事?


19
2018-03-01 13:20


起源


你还在使用交易经理吗? - Jeremy
我不确定配置是什么,但假设我们有一个事务管理器,会影响所述行为吗? - Yuval Adam
我已经读过,有时手动创建一个事务就像你使用事务管理器一样会导致它抛出这个异常。 - Jeremy
这是一个非常好的问题和难以置信的答案。当通过get(...)检索实体时,为什么Hibernate会提交事务?我还没有能够在Hb文档中找到答案。是因为get检查底层事务然后使用它来执行SELECT然后提交它吗?我希望看到关于这个问题的更详细的答案。 - Lisa


答案:


好吧,看起来我们一旦达到了 tx.commit() 行,该事务已经提交。我唯一的猜测是Hibernate已经提交了事务 get()对象。

解决这个问题很简单:

// commit only if tx still hasn't been committed yet (by hibernate)
if (!tx.wasCommitted())
    tx.commit();

40
2018-03-01 13:22



建议的解决方案对我有用。想知道是否有一种智能的方法来查找交易的提交地点? - Anirtak Varma


这是一个非常古老的问题,我认为你已经解决了它(或者放弃了Hibernate),但答案很简单。我很惊讶没人接过来。

您还没有完成session.save(o),因此事务中没有任何内容可以提交。如果您没有更改对象中的任何内容,则提交可能仍然无效,但如果没有更改,您为什么要保存它?

BTW:在session.beginTransaction()之前执行session.get(...)也是完全可以接受的。


7
2017-11-18 03:23



那么,如果我不对数据库进行更改,我不应该开始tx? - user2171669
这对我有用! - rdmueller
我建议谨慎使用这种方法。我认为只有自动提交才能接受,Hibernate强烈反对。没有自动提交,一切都必须在事务中发生 - 甚至是单个选择语句。 - shaddow


我知道这已经解决了;即使我在这里发布我的答案。

我还没找到 wasCommitted() 交易方法。

但是以下代码对我有用:

// commit only, if tx still hasn't been committed yet by Hibernate
if (tx.getStatus().equals(TransactionStatus.ACTIVE)) { 
    tx.commit();
}

5
2017-08-18 03:16



这对我有帮助!!! - Shantaram Tupe


这种情况可能发生的一种情况是代码在使用容器管理事务(CMT)的EJB / MDB中,无论是有意还是因为它是默认值。要使用bean管理的事务,请添加以下注释:

@TransactionManagement(TransactionManagementType.BEAN)

除此之外还有更多,但这是故事的开始。


0
2017-11-22 14:27



你能告诉@TransactionManagement属于哪个包吗?我无法在类路径中找到它 - Jishnu Prathap