2010-04-09 24 views
9

En Hibernate cuando i save() un objeto en una transacción, y luego lo retrotraigo, el objeto guardado aún permanece en la base de datos. Es extraño porque este problema no ocurre con el método update() o delete(), solo con save().

Aquí está el código que estoy usando:Hibernar guardar() y deshacer reversión de transacción

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

Y aquí es el HibernateUtil clase (sólo las funciones involucradas, garantizo el método getSessionFactory() funciona bien - no es un controlador del interceptor, pero doesn 't importa ahora):

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

Gracias

+0

es de confirmación automática conjunto de falsa en la conexión jdbc? –

+0

Sí, lo es ( false). El modo de descarga de la sesión está en modo COMPROMISO. – Mark

Respuesta

8

Compruebe si su base de datos soporta un rollo de vuelta es decir, si está utilizando tablas InnoDB y no hay t MyISAM (puede mezclar tablas transaccionales y no transaccionales, pero en la mayoría de los casos, quiere que todas sus tablas sean InnoDB).

+0

He intentado a tu manera, pero el resultado es siempre el mismo – Mark

+0

@Marcos Ok. Gracias por la respuesta. No me di cuenta de que estaba usando MySQL, he actualizado mi respuesta en consecuencia. –

+0

gracias, ahora funciona como se esperaba – Mark

5

MySQL usa de forma predeterminada el motor de almacenamiento MyIsam. Como MyISAM no admite transacciones, las instrucciones de inserción, actualización y eliminación se escriben directamente en la base de datos. Las instrucciones commit y rollback se ignoran.

Para utilizar la transacción necesita cambiar el motor de almacenamiento de sus tablas. Utilice este comando:

ALTER TABLE table_name ENGINE = InnoDB;

(tenga en cuenta cómo cada vez, que los dos motores de almacenamiento son diferentes y hay que probar que eres la aplicación si es que todavía se comporta como se esperaba)

+4

Desde hace un tiempo, el motor predeterminado de MySQL es InnoDB. –

Cuestiones relacionadas