2011-03-01 99 views
18

考慮一個簡單的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) 

這是怎麼回事?

+0

您是否還在使用事務管理器? – Jeremy 2011-03-01 13:28:01

+0

我不完全確定配置是什麼,但假設我們有一個事務管理器,會影響上述行爲嗎? – 2011-03-01 14:10:27

+0

我讀過,有時手動創建一個事務,就像你在一個事務管理器存在將導致它拋出這個異常。 – Jeremy 2011-03-01 20:46:20

回答

38

好吧,它看起來像一旦我們到達tx.commit()線,交易已被提交。我唯一的猜測是Hibernate已經在提交對象時提交事務。

這種情況的解決方法是簡單的:

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

建議的解決方案適用於我。想知道如果有一個聰明的方法來找到交易的承諾? – 2014-02-25 20:55:01

7

這是一個非常古老的問題,我想你已經解決了它(或休眠放棄),但得到的答覆是可悲簡單。我很驚訝別人沒有把它拿起來。

您還沒有完成session.save(o),所以事務中沒有任何內容會提交。如果您沒有更改對象中的任何內容,提交可能仍不起作用,但如果沒有更改,爲什麼還要保存它?

順便說一句:在session.beginTransaction()之前執行session.get(...)也是完全可以接受的。

+0

因此,如果我不更改數據庫,我不應該開始tx? – user2171669 2014-02-15 07:22:18

+0

這爲我做了詭計! – rdmueller 2015-03-27 06:57:38

+0

我建議您謹慎使用此方法。我認爲這隻有在自動提交的時候纔可以接受,而Hibernate非常沮喪。如果沒有自動提交,所有事務都必須在事務中發生 - 即使是單個選擇語句。 – shaddow 2016-09-19 21:15:34

4

我知道這已經解決了;即使我在這裏發佈我的答案。

我還沒有在交易中找到wasCommitted()方法。

但下面的代碼爲我工作:

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

這對我也有幫助! – 2017-07-27 10:54:06

0

一種情況這可以在發生時的代碼是在EJB/MDB使用容器管理事務(CMT),無論是有意還是因爲它是默認。要使用bean管理的事務,添加以下注釋:

@TransactionManagement(TransactionManagementType.BEAN)

還有更多的東西比,但是這就是故事的開始。