2017-02-22 4 views
1

Ich versuche, 2 Datensätze in meiner Datenbank in einer Transaktion einzufügen. Der zweite Einsatz scheitert aber in der Rollback der erste Einsatz wird nicht gelöscht:Spring Daten jpa geschachtelte Transaktion Rollback nicht löschen einfügen?

@Resource 
     private WebMessageRep rep; //<-- extends JpaRepository 

@Transactional 
    public void test() { 
    WebMessage wm = new WebMessage(.valid params.); 
    wm = rep.save(wm);//<-- save is crud save which is transactional by default 
    WebMessage wm2 = new WebMessage(.invalid params.); 
    rep.save(wm2); 
    } 

(i auch versucht, die Methode speichern Ersetzen mit: jpaContext.getEntityManagerByManagedType (WebMessage.class) .persist (wm); so dass ich benutze nicht die crud retten, aber das Problem noch vorhanden)

I Transaktion sehen die Protokollierung aktiviert ist, was los ist, ich entdeckt:

vor dem Test() aufrufen, eine neue Transaktion erstellt wird, weil @Transactional annotaion:

Creating new transaction with name [com..data.webmessage.WebMessageServiceImpl.test]: PROPAGATION_REQUIRED,ISOLATION_DEFAULT; '' 
Opened new EntityManager [SessionImpl(PersistenceContext[entityKeys=[],collectionKeys=[]];ActionQueue[insertions=ExecutableList{size=0} updates=ExecutableList{size=0} deletions=ExecutableList{size=0} orphanRemovals=ExecutableList{size=0} collectionCreations=ExecutableList{size=0} collectionRemovals=ExecutableList{size=0} collectionUpdates=ExecutableList{size=0} collectionQueuedOps=ExecutableList{size=0} unresolvedInsertDependencies=null])] for JPA transaction 

Aufruf zuerst speichern, die die erste Transaktion sieht:

Found thread-bound EntityManager [SessionImpl(PersistenceContext[entityKeys=[],collectionKeys=[]];ActionQueue[insertions=ExecutableList{size=0} updates=ExecutableList{size=0} deletions=ExecutableList{size=0} orphanRemovals=ExecutableList{size=0} collectionCreations=ExecutableList{size=0} collectionRemovals=ExecutableList{size=0} collectionUpdates=ExecutableList{size=0} collectionQueuedOps=ExecutableList{size=0} unresolvedInsertDependencies=null])] for JPA transaction 

Zweite speichern sieht auch die erste Transaktion:

Found thread-bound EntityManager [SessionImpl(PersistenceContext[entityKeys=[EntityKey[com..shared.WebMessage#107]],collectionKeys=[]];ActionQueue[insertions=ExecutableList{size=1} updates=ExecutableList{size=0} deletions=ExecutableList{size=0} orphanRemovals=ExecutableList{size=0} collectionCreations=ExecutableList{size=0} collectionRemovals=ExecutableList{size=0} collectionUpdates=ExecutableList{size=0} collectionQueuedOps=ExecutableList{size=0} unresolvedInsertDependencies=null])] for JPA transaction 
2017-02-22 14:07:22,000 [   main] DEBUG orm.jpa.JpaTransactionManager    - Participating in existing transaction 

Beim Test Verlassen() ein Commit durchgeführt wurde:

Committing JPA transaction on EntityManager [SessionImpl(PersistenceContext[entityKeys=[EntityKey[com..shared.WebMessage#108], EntityKey[com..shared.WebMessage#107]],collectionKeys=[]];ActionQueue[insertions=ExecutableList{size=2} updates=ExecutableList{size=0} deletions=ExecutableList{size=0} orphanRemovals=ExecutableList{size=0} collectionCreations=ExecutableList{size=0} collectionRemovals=ExecutableList{size=0} collectionUpdates=ExecutableList{size=0} collectionQueuedOps=ExecutableList{size=0} unresolvedInsertDependencies=null])] 

Es schlägt fehl:

Column 'text' cannot be null 
HHH000010: On release of batch it still contained JDBC statements 
HHH000346: Error during managed flush [org.hibernate.exception.ConstraintViolationException: could not execute statement] 
    Initiating transaction rollback after commit exception 

Rollback:

Rolling back JPA transaction on EntityManager [SessionImpl(PersistenceContext[entityKeys=[],collectionKeys=[]];ActionQueue[insertions=ExecutableList{size=0} updates=ExecutableList{size=0} deletions=ExecutableList{size=0} orphanRemovals=ExecutableList{size=0} collectionCreations=ExecutableList{size=0} collectionRemovals=ExecutableList{size=0} collectionUpdates=ExecutableList{size=0} collectionQueuedOps=ExecutableList{size=0} unresolvedInsertDependencies=null])] 

Das Merkwürdige ist, dass der erste Datensatz eingefügt noch in meiner Datenbank (MySQL).

nicht sicher, ob es etwas bedeutet, aber begehen wir haben: Anzeigen = ExecutableList {size = 2} aber auf Rollback ist: Anzeigen = ExecutableList {size = 0}

Weiß jemand, es warum Rollt nicht den ersten Einsatz zurück?

Meine Transaktion Config ist ganz einfach:

<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager"> 
    <property name="entityManagerFactory" ref="emf" /> 
</bean> 

<tx:annotation-driven transaction-manager="transactionManager" /> 

mein Debugger oben abfeuern ergab, dass mein Geschäft nicht mehr aktiv ist, wenn ein Rollback versucht wird. Lassen Sie mich erklären:

[JpaTransactionManager.java]

@Override 
    protected void doRollback(DefaultTransactionStatus status) { 
     JpaTransactionObject txObject = (JpaTransactionObject) status.getTransaction(); 
     if (status.isDebug()) { 
      logger.debug("Rolling back JPA transaction on EntityManager [" + 
        txObject.getEntityManagerHolder().getEntityManager() + "]"); 
     } 
     try { 
      EntityTransaction tx = txObject.getEntityManagerHolder().getEntityManager().getTransaction(); 
      if (tx.isActive()) { 
       tx.rollback(); 
      } 
     } 
     catch (PersistenceException ex) { 
      throw new TransactionSystemException("Could not roll back JPA transaction", ex); 
     } 
     finally { 
      if (!txObject.isNewEntityManagerHolder()) { 
       // Clear all pending inserts/updates/deletes in the EntityManager. 
       // Necessary for pre-bound EntityManagers, to avoid inconsistent state. 
       txObject.getEntityManagerHolder().getEntityManager().clear(); 
      } 
     } 
    } 

Die tx.isActive() in obigen Code gibt false zurück, dies bedeutet, dass kein Rollback ausgeführt wird.

Jetzt ist die große Frage, warum ist meine Transaktion nicht mehr aktiv?

Antwort

1

Nun, es scheint, das Problem war mysql, Tabellen von Frühlingsdaten generiert jpa sind vom Typ Myisam.

Es scheint, dass Myisam wonky geht, wenn Sie einige Arten von Transaktionen verwenden.

Ich konvertierte meine Tabelle in innodb und jetzt funktioniert es: alle eingefügten Zeilen werden gelöscht, wenn die Transaktion fehlschlägt und die Transaktion zurückgesetzt wird. Dies geschieht nicht, wenn die Tabelle vom Typ myisam ist.

Verwandte Themen