Подтвердить что ты не робот

Транзакция, отмеченная только как откат: как мне найти причину

У меня возникают проблемы с совершением транзакции в моем методе @Transactional:

methodA() {
    methodB()
}

@Transactional
methodB() {
    ...
    em.persist();
    ...
    em.flush();
    log("OK");
}

Когда я вызываю методB() из метода A(), метод успешно проходит, и я могу видеть "ОК" в моих журналах. Но затем я получаю

Could not commit JPA transaction; nested exception is javax.persistence.RollbackException: Transaction marked as rollbackOnly org.springframework.transaction.TransactionSystemException: Could not commit JPA transaction; nested exception is javax.persistence.RollbackException: Transaction marked as rollbackOnly
    at org.springframework.orm.jpa.JpaTransactionManager.doCommit(JpaTransactionManager.java:521)
    at org.springframework.transaction.support.AbstractPlatformTransactionManager.processCommit(AbstractPlatformTransactionManager.java:754)
    at org.springframework.transaction.support.AbstractPlatformTransactionManager.commit(AbstractPlatformTransactionManager.java:723)
    at org.springframework.transaction.interceptor.TransactionAspectSupport.commitTransactionAfterReturning(TransactionAspectSupport.java:393)
    at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:120)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
    at org.springframework.aop.framework.Cglib2AopProxy$DynamicAdvisedInterceptor.intercept(Cglib2AopProxy.java:622)
    at methodA()...
  • Контекст метода B полностью отсутствует в исключении - что, я полагаю, это нормально?
  • Что-то в методе B() отметило транзакцию только как откат? Как я могу это узнать? Есть, например, способ проверить что-то вроде getCurrentTransaction().isRollbackOnly()? - вот так я мог бы пройти через этот метод и найти причину.
4b9b3361

Ответ 1

Наконец я понял проблему:

methodA() {
    methodB()
}

@Transactional(noRollbackFor = Exception.class)
methodB() {
    ...
    try {
        methodC()
    } catch (...) {...}
    log("OK");
}

@Transactional
methodC() {
    throw new ...();
}

Случается, что даже если methodB имеет правильную аннотацию, methodC нет. Когда исключение выбрасывается, второй @Transactional в любом случае отмечает первую транзакцию как откат.

Ответ 2

Когда вы помечаете свой метод как @Transactional, появление любого исключения внутри вашего метода будет отмечать окружающий TX только как откат (даже если вы их поймаете). Вы можете использовать другие атрибуты аннотации @Transactional, чтобы предотвратить ее откат как:

@Transactional(rollbackFor=MyException.class, noRollbackFor=MyException2.class)

Ответ 3

Чтобы быстро получить вызывающее исключение без необходимости повторного кодирования или перестройки, установите точку останова на

org.hibernate.ejb.TransactionImpl.setRollbackOnly() // Hibernate < 4.3, or
org.hibernate.jpa.internal.TransactionImpl() // as of Hibernate 4.3

и поднимитесь в стек, как правило, на некоторый Interceptor. Там вы можете прочитать вызывающее исключение из некоторого блока catch.

Ответ 4

Я столкнулся с этим исключением при запуске приложения.

Наконец проблема была в запросе sql. Я имею в виду, что запрос неверен.

пожалуйста, подтвердите свой запрос. Это мое предложение

Ответ 5

Ищите исключения, которые бросаются и попадают в разделы ... вашего кода. Исключения приложений и отката приложений вызывают откат при выкидывании из бизнес-метода, даже если он попадает в другое место.

Вы можете использовать контекст, чтобы узнать, отмечена ли транзакция для отката.

@Resource
private SessionContext context;

context.getRollbackOnly();

Ответ 6

отключите оператора транзакций в Bean.xml

<tx:annotation-driven proxy-target-class="true" transaction-manager="transactionManager"/>
    <bean id="transactionManager"
        class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource"></property>
    </bean>

прокомментируйте эти строки, и вы увидите исключение, вызывающее откат;)

Ответ 7

Нашел хорошее объяснение с решениями: https://vcfvct.wordpress.com/2016/12/15/spring-nested-transactional-rollback-only/

1) удалите @Transacional из вложенного метода, если он действительно не требует управления транзакциями. Так что даже у него есть исключение, оно просто пузырится и не влияет на транзакционные вещи.

ИЛИ ЖЕ:

2) если вложенному методу нужен контроль транзакций, сделайте его REQUIRE_NEW для политики распространения таким образом, даже если выдает исключение и помечает только как откат, на вызывающего это не повлияет.

Ответ 8

пожалуйста, проверьте ваш @Transactional импорт, он должен быть

import javax.transaction.Transactional;

Ответ 9

применить приведенный ниже код в productRepository

@Query("update Product set prodName=:name where prodId=:id ") @Transactional @Modifying int updateMyData(@Param("name")String name, @Param("id") Integer id);

в то время как в тесте junit применяется ниже код

@Test
public void updateData()
{
  int i=productRepository.updateMyData("Iphone",102);

  System.out.println("successfully updated ... ");
  assertTrue(i!=0);

}

это работает нормально для моего кода