2011-03-01 8 views
18

Considere este escenario simple Hibernate:transacción de hibernación no se ha iniciado con éxito

session = getHibernateSession(); 
tx = session.beginTransaction(); 
SomeObject o = (SomeObject) session.get(SomeObject.class, objectId); 
tx.commit(); 

Este código produce la siguiente excepción:

org.hibernate.TransactionException: Transaction not successfully started 
    at org.hibernate.transaction.JDBCTransaction.commit(JDBCTransaction.java:100) 
    at com.bigco.package.Clazz.getSomeData(Clazz.java:1234) 

¿Qué está pasando?

+0

¿También está usando un administrador de transacciones? – Jeremy

+0

No estoy seguro de cuál es la configuración, pero suponiendo que tengamos un administrador de transacciones, ¿afectará dicho comportamiento? –

+0

He leído que a veces la creación manual de una transacción como la que tiene con un administrador de transacciones presente hará que arroje esta excepción. – Jeremy

Respuesta

38

Bueno, parece que una vez que llegamos a la línea tx.commit(), la transacción ya se ha confirmado. Mi única conjetura es que Hibernate ya confirma la transacción cuando get() ing el objeto.

La solución a esto es simple:

// commit only if tx still hasn't been committed yet (by hibernate) 
if (!tx.wasCommitted()) 
    tx.commit(); 
+0

La solución sugerida funcionó para mí. Sin embargo, me gustaría saber si existe una forma inteligente de encontrar dónde se cometió la transacción. –

7

Ésta es una pregunta muy viejo y me imagino que ya has resuelto él (o renunciado a Hibernate), pero la respuesta es sencilla trágicamente. Me sorprende que nadie más lo haya recogido.

No ha hecho una session.save (o), por lo que no hay nada en la transacción que comprometer. La confirmación aún puede no funcionar si no ha cambiado nada en el objeto, pero ¿por qué querría guardarlo si no ha cambiado nada?

BTW: También es perfectamente aceptable hacer la session.get (...) antes de la session.beginTransaction().

+0

Entonces, si no realizo cambios en la base de datos, ¿no debería comenzar tx? – user2171669

+0

¡esto hizo el truco para mí! – rdmueller

+0

Recomiendo precaución con este enfoque. Creo que esto solo es aceptable con Autocommit on, que Hibernate desalienta vigorosamente. Sin compromiso automático, todo DEBE suceder dentro de una transacción, incluso solo declaraciones de selección. – shaddow

4

Me enteré de que esto ya está resuelto; a pesar de que estoy publicando mi respuesta aquí.

No he encontrado wasCommitted() método de la transacción.

Pero el siguiente código que funcionó para mí:

// commit only, if tx still hasn't been committed yet by Hibernate 
if (tx.getStatus().equals(TransactionStatus.ACTIVE)) { 
    tx.commit(); 
} 
+0

esto me ayudó a mí también !!! –

0

Una situación esto puede suceder en es cuando el código está en un EJB/MDB utilizando transacciones gestionadas por contenedor (CMT), ya sea intencional o porque es la defecto. Para utilizar las transacciones de frijol gestionados, agregue la siguiente anotación:

@TransactionManagement (TransactionManagementType.BEAN)

Hay más que eso, pero eso es el comienzo de la historia.

Cuestiones relacionadas