交易未回滚

时间:2014-06-19 17:03:25

标签: java spring transactions spring-transactions

如果出现错误,我有一组操作我想要回滚。

我的班级

public class BSException extends RuntimeException{
...
}

public class saleFacade{

  public update(){

    for (){
      try{
        renewSale();
      }
      catch(BSException){
        logger.error();
      }
    }
  }

  @Transactional
  public renewSale(){
    try{
      findSale(); // read only Transactional
      xxx.renewSpecialSale();
     }
     catch(Exception e){
       logger.error(...);
     }
 }
}


public class xxx(){
  public void renewSpecialSale(){    
    payFee(); //write to db
    if(error){
      throw new BSException();
    }
  }

 @Transactional(propagation = Propagation.REQUIRED)
 public payFee(){
   try{
     ...
   }
   catch(BsException e){
     ...
   }
   catch(Exception e){
     ...
   }
 }
}

@Configuration
@EnableTransactionManagement
public class DBConfiguration{
  @Bean(name = "dataSource")
  public BasicDataSource dataSource(){
  ...
  }
}

Inn renewSpecialSale错误是throw。

在renewSale方法中,如果有错误,我想回滚。 现在什么都没有回滚

任何想法?

4 个答案:

答案 0 :(得分:2)

如果在它离开方法之前捕获异常,则包装方法的代理无法知道抛出异常。

完全删除try-catch或重新抛出异常,以便异常可以保留您标记为@Transactional的方法(并被代理拦截),并且将发生回滚。

我建议从所有这些方法中删除异常处理。设置一个中央异常处理程序,以便从控制器抛出的任何东西都被捕获并记录,否则会抛出异常。

确保每个执行事务的类都是单独注释的,如果在方法级别进行注释,那么应该对每个执行事务的方法进行注释。从同一对象上的非事务方法调用事务方法不会通过代理(代理只拦截来自对象外部的那些调用,并且只有当该方法被标记为事务时才这样)所以它不是'交易的一部分(+1到Peter's answer用于指出这一点。)

我不知道你的错误标志在做什么,这看起来很奇怪。 Spring服务不应该有状态。如果您修复了异常处理,则不需要错误标记。

答案 1 :(得分:1)

问题来自于您对Method调用的嵌套和@Transactional的使用。默认情况下,弹簧交易管理

  

在代理模式(默认设置)下,只拦截通过代理进入的外部方法调用。这意味着实际上,自调用目标对象中的一个方法调用目标对象的另一个方法,即使被调用的方法用@Transactional标记,也不会在运行时导致实际的事务。 Spring Transaction Management

这意味着,呼叫

xxx.payFee()
通过

调用时,

不会被事务包围

saleFacade.update() -> saleFacade.renewSale() -> xxx.renewSpecialSale()

据我所知,你至少有这些选项

  • 将xxx.renewSpecialSale()标记为@Transactional
  • 将saleFacade.update()标记为@Transactional
  • 标记类xxx和saleFacade @Transactional

答案 2 :(得分:0)

从您的方法中删除try catch块并将其放在下面的代码行

 @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)

使用这行代码

@Transactional(propagation = Propagation.REQUIRED)

在上面的代码spring容器处理整个事务管理,如果我们提供rollback属性,它会自动管理是否发生任何类型的异常它会回滚你的事务

并确保您在配置文件中输入了事务,如下所示

 <tx:annotation-driven />

以及

我希望它一定能帮到你

答案 3 :(得分:0)

此外,您可以创建自己的自定义异常类并将其抛出。

从标有RuntimeException的方法中抛出任何@Transactional

默认情况下,所有RuntimeExceptions回滚交易,而已检查的例外情况不适用。这是EJB的遗产。您可以使用rollbackFor()noRollbackFor()注释参数进行配置:

@Transactional(rollbackFor=Exception.class)

这将在抛出任何异常后回滚事务。

@Transactional(rollbackFor = MyCheckedException.class)
public void foo() {
    throw new RuntimeException();    
}