Hibernate-Transaktion wurde nicht erfolgreich gestartet

Betrachten Sie dieses einfache Hibernate-Szenario:

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

Dieser Code erzeugt die folgende Ausnahme:

 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) 

Was ist los?

Nun, es sieht so aus, als tx.commit() die Transaktion, sobald wir die tx.commit() Zeile erreicht haben, bereits festgeschrieben wurde. Meine einzige Vermutung ist, dass Hibernate die Transaktion bereits beim Abrufen des Objekts festschreibt.

Die Lösung dafür ist einfach:

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

Dies ist eine wirklich alte Frage und ich denke, Sie haben es bereits getriggers (oder auf Hibernate aufgegeben), aber die Antwort ist tragisch einfach. Ich bin überrascht, dass niemand anders es aufgegriffen hat.

Sie haben noch keine session.save (o) ausgeführt, sodass nichts in der Transaktion zu committen ist. Das Commit funktioniert möglicherweise immer noch nicht, wenn Sie an dem Objekt nichts geändert haben, aber warum sollten Sie es speichern, wenn sich nichts geändert hat?

BTW: Es ist auch vollkommen akzeptabel, die session.get (…) vor der session.beginTransaction () zu machen.

Ich habe erfahren, dass dies bereits getriggers ist; obwohl ich meine Antwort hier poste.

Ich habe die Methode wasCommitted() für die Transaktion nicht gefunden.

Aber der folgende Code funktionierte für mich:

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

Eine Situation, in der dies passieren kann, ist, wenn sich der Code in einem EJB / MDB befindet, das containergesteuerte Transaktionen (CMT) verwendet, entweder absichtlich oder weil es der Standardwert ist. Fügen Sie die folgende Anmerkung hinzu, um Bean-Managed-Transaktionen zu verwenden:

@TransactionManagement (TransaktionsManagementType.BEAN)

Es gibt mehr als das, aber das ist der Anfang der Geschichte.