简体   繁体   English

Hibernate save()和事务回滚

[英]Hibernate save() and transaction rollback

In Hibernate when i save() an object in a transaction, and then i rollback it, the saved object still remains in the DB. 在Hibernate中,当我在事务中save()一个对象,然后我回滚它时,保存的对象仍然保留在数据库中。 It's strange because this issue doesn't happen with the update() or delete() method, just with save() . 这很奇怪,因为update()delete()方法不会发生这个问题,只需使用save()

Here is the code i'm using: 这是我正在使用的代码:

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

And here is the HibernateUtil class (just the involved functions, i guarantee the getSessionFactory() method works well - there is an Interceptor handler, but it doesn't matter now): 这里是HibernateUtil类(只涉及函数,我保证getSessionFactory()方法运行良好 - 有一个Interceptor处理程序,但它现在无关紧要):

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

Thanks 谢谢

检查您的数据库是否支持回滚,即如果您使用的是InnoDB表而不是MyISAM(您可以混合使用事务性表和非事务性表,但在大多数情况下,您希望所有表都是InnoDB)。

MySQL by default uses the MyIsam storage engine. MySQL默认使用MyIsam存储引擎。 As the MyISAM does not support transactions, insert, update and delete statements are directly written to the database. 由于MyISAM不支持事务,因此insert,update和delete语句直接写入数据库。 The commit and rollback statements are ignored. 提交和回滚语句将被忽略。

In order to use transaction you need to change the storage engine of you tables. 要使用事务,您需要更改表的存储引擎。 Use this command: 使用此命令:

ALTER TABLE table_name ENGINE = InnoDB;

(note how ever, that the two storage engines are different and you need to test you're application if it still behaves as expected) (请注意,两个存储引擎是不同的,如果它仍然按预期运行,您需要测试您的应用程序)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM