运用@Transactional,自己抛出异常时不会回滚的原因,经验之谈

 

查看spring API可知 http://www.kuqin.com/spring2.0_doc/index.html

对EJB来说,默认的行为是EJB容器在遇到系统异常 (通常指运行时异常)时自动回滚当前事务。EJB CMT遇到应用异常 (例如,除了java.rmi.RemoteException外别的checked exception)时并不会自动回滚。默认式Spring处理声明式事务管理的规则遵守EJB习惯(只在遇到unchecked exceptions时自动回滚),但通常定制这条规则会更有用。

所以

package x.y.service;

public class DefaultFooService implements FooService {

    public Foo getFoo(String fooName) {
        throw new UnsupportedOperationException();
    }

    public Foo getFoo(String fooName, String barName) {
        throw new UnsupportedOperationException();
    }

    public void insertFoo(Foo foo) {
        throw new UnsupportedOperationException();
    }

    public void updateFoo(Foo foo) {
        throw new UnsupportedOperationException();
    }
}

(对该例的目的来说,上例中实现类(DefaultFooService)的每个方法在其方法体中抛出UnsupportedOperationException的做法是恰当的,我们可以看到,事务被创建出来,响应UnsupportedOperationException的抛出,然后回滚。)

@Transactional 有关的设置

在最简单的形式下,@Transactional指定一个接口、类、方法必须是事务性的,其默认事务语义为:read/write,PROPAGATION_REQUIREDISOLATION_DEFAULTTIMEOUT_DEFAULT,而且仅当遇到RuntimeException时回滚,而不是Exception

改变事务设置的其他可选属性

 

Table 9.1.Transactional注解的属性

属性类型描述
传播性枚举型:Propagation可选的传播性设置 (默认值:PROPAGATION_REQUIRED
隔离性枚举型:Isolation可选的隔离性级别(默认值:ISOLATION_DEFAULT
只读性布尔型读写型事务 vs. 只读型事务(默认值:false,即只读型事务)
回滚异常类(rollbackFor)一组Class类的实例,必须是Throwable的子类一组异常类,遇到时 确保 进行回滚。默认情况下checked exceptions不进行回滚,仅unchecked exceptions(即RuntimeException的子类)才进行事务回滚。
回滚异常类名(rollbackForClassname)一组Class类的名字,必须是Throwable的子类一组异常类名,遇到时 确保 进行回滚
不回滚异常类(noRollbackFor)一组Class类的实例,必须是Throwable的子类一组异常类,遇到时确保 回滚。
不回滚异常类名(noRollbackForClassname)一组Class类的名字,必须是Throwable的子类一组异常类,遇到时确保 回滚

 

我们推荐你参考@Transactional注解的javadoc,其中详细列举了上述各项属性及其可选值。

 

————————————————————————————————————

通过以上可知,在spring 中运用@Transactional 注解,自己抛出异常UnsupportedOperationException会 回滚,抛Exception异常,得作相关的配置才会回滚。