4 Stimmen

Hibernate Entity Manager automatisches Auslösen vor der Abfrage und Übernehmen der Änderungen in der Datenbank im Transaktionsprozess

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...

6voto

Quincy Punkte 4323

Problem gelöst. Der Grund dafür ist, dass Tabellen in der MySQL standardmäßig den MyISAM Engine verwenden und Tabellen, die diese Engine verwenden, keine Transaktionen unterstützen. Die Umstellung der Tabellen auf InnoDB hat das Problem behoben. Hoffentlich ist dies für jemanden nützlich, damit sie nicht so viel Zeit verschwenden wie ich. :(

2voto

Luke Punkte 3246

Was ist als FlushModeType des entityManager festgelegt

void setFlushMode(FlushModeType flushMode) 
Legt den Flush-Modus fest, der für alle Objekte im Persistenzkontext gilt.

Die Methode nimmt ein hier definiertes Enum an.

Enum Constant Summary

AUTO
       (Standard) Das Flushen erfolgt bei Abfrageausführung.

COMMIT
       Das Flushen erfolgt beim Transaktionscommit.

Versuchen Sie auch, das Folgende zu überprüfen

@PersistenceContext(unitName="MyEJB") private EntityManager em

nachdem Sie die Entity Manager Factory deklariert haben.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X