【问题标题】:@transaction - roll back failing@transaction - 回滚失败
【发布时间】:2014-04-04 11:49:11
【问题描述】:
@Override
    @Transactional(rollbackFor = { RuntimeException.class, Exception.class}, propagation = Propagation.REQUIRED)
    public String upload(ObjectVO vo) throws CustomException {
    .......
    }

在此服务中,我将插入两个表。如果在处理应该在第一个表之后插入的第二个表的数据(如强制字段检查)时出现异常,是否应该回滚在同一事务中插入第一个表中的数据?就我而言,我没有让它回滚。预期的行为是什么? (是的,我没有捕捉到异常,它是一个自定义异常,包含在rollbackFor 子句中,并且正在被抛出)
(I am using hibernate) DAO 层执行getSession().save(entity);getSession() 返回 currentSession)

(所以第一个表中的数据仍然存在)

这些表不相关。

<tx:annotation-driven/>

<bean id="transactionManager"
        class="org.springframework.jdbc.datasource.DataSourceTransactionManager"
        lazy-init="true">
        <property name="dataSource" ref="dataSource" />
    </bean>

【问题讨论】:

  • 你确定是Spring管理的Service实例吗?
  • 我假设您的 customException 是checkedException。如果它是 CustomException ,如果你没有明确地被捕获,它应该是方法签名的一部分(作为 throw ) - 我在哪里错了吗?
  • 是的。 sory 是一个错字。固定
  • 与您的问题无关,但这里有些多余 rollbackFor = { RuntimeException.class, Exception.class, CustomException.class } 您的 CustomException 是运行时或已检查(异常子类)异常,实际上您甚至可以将所有内容替换为 rollbackFor = { Throwable.class}
  • 首先,使用 log4j 启​​用日志记录并将级别设置为调试或跟踪:Spring 类将输出显示事务创建等的详细日志记录。如果您看不到显示正在创建的事务的日志记录输出,那么您有一些东西配置错误。如果它存在并且没有回滚,那么是代码问题。

标签: java spring hibernate transactions spring-transactions


【解决方案1】:

您确定代理实际应用于方法调用吗?

假设您使用经典的动态代理(不是 aspectJ 代理),您能否确保从其类外部调用该方法?

[编辑] 如果您使用休眠,请将您的事务管理器切换到 HibernateTransactionManager

【讨论】:

  • 我没有得到你。 “从类外调用方法”部分
  • 哪个方法实际调用了带注释的方法?它在哪里
  • 从控制器调用它
  • 控制器使用DI获取bean引用?
  • 是的。但即使从测试用例调用也没有任何区别
【解决方案2】:

首先: 按照建议,首先通过在 log4j 中添加以下内容来启用日志

log4j.category.org.springframework=ALL

第二: 如果您从同一个 Servcie 类(比如 xxxMethod)中的另一个方法调用上传方法,并且 xxxMethod 没有被 Transaction 注释。那么就不会有任何回滚。 因为代理中方法到方法之间的调用不是由 Spring 上下文处理的。因此它将无法包装交易。

如果第二个无效,请启用日志验证日志。您的日志应显示事务何时开始、何时结束以及添加到事务上下文中的方法。

如下图

DEBUG org.springframework.transaction.annotation.AnnotationTransactionAttributeSource - Adding transactional method 'saveDomain' with attribute: PROPAGATION_REQUIRED,ISOLATION_DEFAULT; ''


2014-04-04 10:25:24,276 [main] TRACE org.springframework.orm.jpa.JpaTransactionManager - Triggering beforeCompletion synchronization
2014-04-04 10:25:24,276 [main] DEBUG org.springframework.orm.jpa.JpaTransactionManager - Initiating transaction rollback

所以

注意**,如果您的 DAO 层还使用 Transaction 和传播规则注释为 Propagation.REQUIRES_NEW - Dao 方法被视为单独的 UoW 。所以从服务层抛出异常不会回滚之前的事务。

一般来说 - 建议将事务保持在一层,最好使用Service - Layer

【讨论】:

  • 感谢有关春季环境的宝贵信息。但问题出在事务管理器上。修复它
【解决方案3】:

我记得我也遇到过这样的问题。我的问题与正确的配置有关。 例如:您是否在 TransactionManager 声明中指定了如下内容:

transactionManager.setRollbackOnCommitFailure(true);

您还可以使用调试器并在您的 TransactionManager 实现中捕获执行。你有一个类似回滚的方法,你会看到这个操作被省略的原因。

【讨论】:

  • 我没有看到需要指定 transactionManager.setRollbackOnCommitFailure(true); 的地方是不是默认为true?
  • 我作为提供者使用:JpaTransactionManager,方法在 AbstractPlatformTransactionManager 中指定。如果您正在使用其他东西。只需使用调试器并检查是否没有额外的回滚条件。
  • 我想补充一下:默认情况下这个值为false:private boolean rollbackOnCommitFailure = false;在 processCommit 的代码中是: if (isRollbackOnCommitFailure()) { doRollbackOnCommitException(status, ex); }
  • 你在使用休眠??所以你应该改用 HibernateTransactionManager
  • 所以,对不起,我不知道如何提供帮助 :( 但如果我猜到问题出在配置上 -> 调试器会告诉你真相。你也可以试试 JpaTransactionManager 我正在使用这个Hibernate 也是如此。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-09-15
  • 2015-09-16
  • 2019-07-27
  • 1970-01-01
  • 1970-01-01
  • 2015-04-26
  • 1970-01-01
相关资源
最近更新 更多