Ich verwende Hibernate 3.6.0 mit JPA 2 auf Jboss AS 6.0.0 final. In einem meiner EJBs gibt es eine Methode, die Entity-Werte aktualisiert und eine Abfrage durchführt. Die gesamte Methode läuft in einer BMT-Transaktion. Wenn etwas schief geht, sollten alle Änderungen zurückgerollt und nicht in die DB übernommen werden.
Die Datenbank ist MySql.
Vor dem Ausführen der JPA-Abfrage wird JPA die geänderten Zustände automatisch auf die DB übertragen, um sicherzustellen, dass keine veralteten Daten zurückgegeben werden. Innerhalb meiner Methode aktualisiert und übernimmt der Auto-Flush jedoch direkt die Änderungen in die DB und auch wenn danach etwas schiefgeht, werden die Änderungen nicht zurückgerollt. Deshalb frage ich mich, ob meine Konfiguration falsch ist oder ob hier ein Fehler vorliegt.
EJB
@Stateless(mappedName = "MyManagementBean")
@Local
@TransactionManagement(TransactionManagementType.BEAN)
public class MyManagement implements MyManagementLocal,MyManagementRemote {
@PersistenceUnit(unitName="MyEjb") EntityManagerFactory emf;
@Resource UserTransaction utx;
@Resource SessionContext ctx;
/**
* Standardkonstruktor.
*/
public MyManagement () {
// TODO Auto-generierter Konstruktorstub
}
public void dosomething(String id) throws Exception
{
try {
utx.begin();
em = emf.createEntityManager();
Myline line = em.find(Myline.class, id);
line.setStatus("R");
Stromg q += " from Myline as line ";
//auto flush apply here and directly committed to DB...
Iterator iter = em.createQuery(q).getResultList().iterator();
em.flush();
utx.commit();// changes should only commit after this
}
catch (Exception e) {
e.printStackTrace();
if (utx != null) utx.rollback();
throw e; // or display error message
}
finally {
em.close();
}
}
}
persistence.xml
org.hibernate.ejb.HibernatePersistence
java:MyDS
com.quincy.entity.MyLine
hibernate.cfg.xml
org.hibernate.transaction.JBossTransactionManagerLookup
true
3
mysql-ds.xml
MyDS
jdbc:mysql://10.10.150.57:3306/myds
com.mysql.jdbc.Driver
user
pwd
org.jboss.resource.adapter.jdbc.vendor.MySQLExceptionSorter
mySQL
Bei weiteren Nachforschungen habe ich herausgefunden, dass bei jedem Flush die dirty changes direkt in die DB geschrieben und übernommen werden. Wenn ich den flush() entferne, funktioniert alles wie gewünscht. Es gibt jedoch systemausgelöste Flush-Vorgänge vor der Abfrage und ich denke, dass dies notwendig ist.
Es scheint, dass die DB automatisch committed wird. Ich habe versucht, die Eigenschaft hibernate.connection.autocommit
auf false
zu setzen, aber das Problem bleibt bestehen und es wird eine EJB-Warnung wegen Verstoßes gegen die Spezifikation angezeigt.
UPDATE: Die Ursache sollte von mysql kommen. Wenn ich zu einem mssql-Server wechsle, verschwindet das Problem. Ich habe auch mysql mit xa-datasource
ausprobiert, aber ohne Erfolg...