2010-04-09 37 views
9

Trong Hibernate khi i save() một đối tượng trong một giao dịch, và sau đó tôi rollback nó, đối tượng đã lưu vẫn còn trong DB. Thật lạ vì vấn đề này không xảy ra với phương thức update() hoặc delete(), chỉ với save().

Đây là mã tôi đang sử dụng:Hibernate save() và rollback giao dịch

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

Và đây là HibernateUtil lớp (chỉ cần các chức năng liên quan, tôi đảm bảo phương pháp getSessionFactory() hoạt động tốt - có một handler Interceptor, nhưng nó doesn 't quan trọng bây giờ):

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(); 
    } 
} 

Cảm ơn

+0

là autocommit thiết lập để sai trên kết nối jdbc? –

+0

Vâng, đó là ( false). Chế độ xả của phiên là ở chế độ COMMIT. – Mark

Trả lời

8

Kiểm tra xem cơ sở dữ liệu của bạn hỗ trợ một cuộn lại tức là nếu bạn đang sử dụng các bảng InnoDB và không t MyISAM (bạn có thể trộn các bảng giao dịch và phi giao dịch nhưng trong hầu hết các trường hợp, bạn muốn tất cả các bảng của mình là InnoDB).

+0

Tôi đã thử theo cách của bạn, nhưng kết quả luôn giống như – Mark

+0

@Marcos Ok. Cảm ơn vì bạn đã phản hồi. Tôi đã không phát hiện ra bạn đang sử dụng MySQL, tôi đã cập nhật câu trả lời của tôi cho phù hợp. –

+0

cảm ơn người đàn ông, bây giờ nó hoạt động như mong đợi – Mark

5

Theo mặc định, MySQL sử dụng công cụ lưu trữ MyIsam. Vì MyISAM không hỗ trợ các giao dịch, chèn, cập nhật và xóa các câu lệnh được ghi trực tiếp vào cơ sở dữ liệu. Các câu lệnh commit và rollback bị bỏ qua.

Để sử dụng giao dịch, bạn cần thay đổi công cụ lưu trữ của các bảng. Sử dụng lệnh này:

ALTER TABLE table_name ENGINE = InnoDB;

(lưu ý cách bao giờ hết, rằng hai công cụ lưu trữ khác nhau và bạn cần phải kiểm tra bạn ứng dụng đang nếu nó vẫn cư xử như dự kiến)

+4

Trong một thời gian, công cụ mặc định của MySQL là InnoDB. –

Các vấn đề liên quan