2017-02-22 62 views
1

Я пытаюсь вставить 2 записи в мою базу данных в транзакции. Вторая вставка терпит неудачу, но в откате первый вкладыш не удаляется:Данные весны jpa вложенные транзакционные откаты, не удаляя вставку?

@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); 
    } 

(я также попытался заменить метод сохранения с: jpaContext.getEntityManagerByManagedType (WebMessage.class) .persist (СУС), так что я не использовать отбросы сохранить, но проблема все еще существует)

Я включил ведение журналов транзакций, чтобы увидеть, что происходит, я обнаружил:

Перед вызовом теста() новая транзакция создается потому, что @Transactional аннотация:

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 

Вызов первого сохранения, который видит первую сделку:

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 

Второй бросок видит также первая сделка:

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 

При выходе из тестового() коммита сделано:

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])] 

Не удается:

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 

Откат:

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])] 

Самое странное в том, что первый вставленной записи еще в моей базе данных (MySQL).

Не уверен, если это означает что-нибудь, но при фиксации мы имеем: вставки = ExecutableList {SIZE = 2} но откатить это: Вставки = ExecutableList {размер = 0}

Кто-нибудь знает, почему это не откатывает первую вставку?

Моя сделка конфигурации довольно прост:

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

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

розжига мой отладчик показал, что моя транзакция больше не активна, когда откат пытался. Поясню:

[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(); 
      } 
     } 
    } 

tx.isActive() в коде выше возвращает ложь, это означает, что отката назад не выполняется.

Теперь большой вопрос, почему моя транзакция больше не активна?

ответ

1

Ну, похоже, проблема была в mysql, таблицы, генерируемые данными весны jpa, имеют тип myisam.

Похоже, что при использовании некоторых типов транзакций myisam не работает.

Я преобразовал свой стол в innodb, и теперь он работает: все вставленные строки удаляются при сбое транзакции и транзакции откатываются. Этого не происходит, если таблица имеет тип myisam.