Hibernate save () и откат транзакции - PullRequest
9 голосов
/ 09 апреля 2010

В Hibernate, когда я save() объект в транзакции, а затем я откат его, сохраненный объект все еще остается в БД. Это странно, потому что эта проблема не возникает с методом update() или delete(), а только с save().

Вот код, который я использую:

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

А вот класс 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();
    }
}

Спасибо

Ответы [ 2 ]

8 голосов
/ 11 апреля 2010

Проверьте, поддерживает ли ваша база данных откат, т. Е. Используете ли вы таблицы InnoDB, а не MyISAM (вы можете смешивать транзакционные и нетранзакционные таблицы, но в большинстве случаев вы хотите, чтобы все ваши таблицы были InnoDB).

5 голосов
/ 11 апреля 2010

MySQL по умолчанию использует механизм хранения MyIsam. Поскольку MyISAM не поддерживает транзакции, операторы вставки, обновления и удаления напрямую записываются в базу данных. Операторы commit и rollback игнорируются.

Чтобы использовать транзакцию, вам нужно изменить механизм хранения ваших таблиц. Используйте эту команду:

ALTER TABLE table_name ENGINE = InnoDB;

(заметьте, однако, что два механизма хранения различны, и вам нужно проверить приложение, если оно все еще работает как положено)

...