2010-04-09 109 views
9

在Hibernate中當我在一個事務中有一個對象,然後我回滾它時,保存的對象仍然保留在數據庫中。這很奇怪,因爲這個問題不會發生在update()delete()方法中,只是save()

這裏是我使用的代碼:Hibernate save()和事務回滾

DbEntity dbEntity = getDbEntity(); 
HibernateUtil.beginTransaction(); 
Session session = HibernateUtil.getCurrentSession(); 
session.save(dbEntity); 
HibernateUtil.rollbackTransaction(); 

這裏是的HibernateUtil類(就所涉及的功能,我保證getSessionFactory()方法效果很好 - 有一個攔截處理程序,但它不「T現在重要):

private static final ThreadLocal<Session> threadSession = new ThreadLocal<Session>(); 
private static final ThreadLocal<Transaction> threadTransaction = new ThreadLocal<Transaction>(); 

/** 
* Retrieves the current Session local to the thread. 
* <p/> 
* If no Session is open, opens a new Session for the running thread. 
* 
* @return Session 
*/ 
public static Session getCurrentSession() 
    throws HibernateException { 
    Session s = (Session) threadSession.get(); 
    try { 
     if (s == null) { 
      log.debug("Opening new Session for this thread."); 
      if (getInterceptor() != null) { 
       log.debug("Using interceptor: " + getInterceptor().getClass()); 
       s = getSessionFactory().openSession(getInterceptor()); 
      } else { 
       s = getSessionFactory().openSession(); 
      } 
      threadSession.set(s); 
     } 
    } catch (HibernateException ex) { 
     throw new HibernateException(ex); 
    } 
    return s; 
} 

/** 
* Start a new database transaction. 
*/ 
public static void beginTransaction() 
    throws HibernateException { 
    Transaction tx = (Transaction) threadTransaction.get(); 
    try { 
     if (tx == null) { 
      log.debug("Starting new database transaction in this thread."); 
      tx = getCurrentSession().beginTransaction(); 
      threadTransaction.set(tx); 
     } 
    } catch (HibernateException ex) { 
     throw new HibernateException(ex); 
    } 
} 

/** 
* Rollback the database transaction. 
*/ 
public static void rollbackTransaction() 
    throws HibernateException { 
    Transaction tx = (Transaction) threadTransaction.get(); 
    try { 
     threadTransaction.set(null); 
     if (tx != null && !tx.wasCommitted() && !tx.wasRolledBack()) { 
      log.debug("Tyring to rollback database transaction of this thread."); 
      tx.rollback(); 
     } 
    } catch (HibernateException ex) { 
     throw new HibernateException(ex); 
    } finally { 
     closeSession(); 
    } 
} 

感謝

+0

是自動提交設置爲false jdbc連接? – 2010-04-09 13:54:28

+0

是的,它是( false)。會話的刷新模式處於COMMIT模式。 – Mark 2010-04-09 19:58:42

回答

8

檢查你的數據庫支持回滾也就是說,如果你正在使用InnoDB表和無•MyISAM(您可以混合使用事務性表和非事務性表,但在大多數情況下,您希望所有表都是InnoDB)。

+0

我試過你的方式,但結果總是一樣的 – Mark 2010-04-11 00:29:21

+0

@Marcos好的。感謝您的反饋。我沒有發現你使用的是MySQL,我已經相應地更新了我的答案。 – 2010-04-11 01:07:58

+0

謝謝,現在它按預期工作 – Mark 2010-04-12 01:19:10

5

MySQL默認使用MyIsam存儲引擎。由於MyISAM不支持事務,插入,更新和刪除語句直接寫入數據庫。提交和回滾語句被忽略。

爲了使用事務,您需要更改表格的存儲引擎。使用此命令:

ALTER TABLE table_name ENGINE = InnoDB;

(注意怎麼過,這兩個存儲引擎是不同的,你需要測試你的應用程序,如果它仍然表現如預期)

+4

有一段時間了,MySQL的默認引擎是InnoDB。 – 2014-03-13 14:50:47