0046 @Transactional注解的几个参数--事务传播控制--事务隔离级别--异常与回滚

@Transactianal注解有一些属性,见Spring-Framework-Reference Table17.3 Transactional-settings

@Transactional(propagation=Propagation.REQUIRED)           //控制事务传播。默认是Propagation.REQUIRED
@Transactional(isolation=Isolation.DEFAULT)                //控制事务隔离级别。默认跟数据库的默认隔离级别相同
@Transactional(readOnly=false)                             //控制事务可读写还是只可读。默认可读写
@Transactional(timeout=30)                                 //控制事务的超时时间,单位秒。默认跟数据库的事务控制系统相同,又说是30秒
@Transactional(rollbackFor=RuntimeException.class)         //控制事务遇到哪些异常才会回滚。默认是RuntimeException
@Transactional(rollbackForClassName=RuntimeException)      //同上
@Transactional(noRollbackFor=NullPointerException.class)   //控制事务遇到哪些异常不会回滚。默认遇到非RuntimeException不会回滚
@Transactional(noRollbackForClassName=NullPointerException)//同上

控制事务传播----propagation属性

事务的传播是指:
    A.f1()有事务X
    B.f2()有事务Y
    当A.f1()调用B.f2()的时候,B.f2()中的代码执行哪个事务

该属性可能的值有(以下属性值加在B.f2()上来理解):

Propagation.NEVER:
    B.f2()不能在任何事务下执行,如果A.f1()调用它,那么抛异常。绝不接受,硬给就拼命

Propagation.NOT_SUPPORTED:
    B.f2()不需要在事务中执行。如果被需要事务X的A.f1()调用,那么事务X被挂起,B.f2()执行完毕X才恢复。不接受,硬给也不收

Propagation.REQUIRES_NEW:
    如果A.f1()调用B.f2(),那么事务X被挂起,重新创建一个事务Y,B.f2()在事务Y中执行,Y执行完毕再继续X事务。接受,给的不收,用自己的

Propagation.SUPPORTS:
    如果B.f2()被A.f1()调用,那么执行X事务;如果被没有事务的方法调用,那么就在没有事务的环境下执行。接受,给就收下,不给也不要

Propagation.REQUIRED:
    如果A.f1()调用B.f2(),那么B.f2()在事务X中执行;如果B.f2()没有被调用,那就执行自己的事务Y。接受,给就收下,不给就用自己的

Propagation.MANDATORY:
    B.f2()不能开启自己的事务,只能被开启了事务的A.f1()调用,如果被没有开启事务其他的方法调用,则抛异常。自己没有,给,必须给,不给就哭

Propagation.NESTED:
    看不懂

控制事务隔离级别----属性isolation

事务隔离级别是数据库的概念,在多个事务对一批记录进行操作的时候,可能出现各种冲突的情况

该属性的可能值有:
Isolation.READ_UNCOMMITED
    读未提交
    可以读到其他事务未提交的数据。导致脏读(dirty read)

Isolation.READ_COMMITED
    读已提交。这是很多数据库的默认隔离级别,但不是MySQL的。
    不能读到其他事务未提交的数据,只能读到已提交的数据。解决了脏读,可导致重读幻读
    重读:在预读之后,commit之前,其他事务更新了数据,导致两次读到的数据不相同
    幻读:在预读之后,commit之前,其他事务插入数据,导致两次读到的数据条数不相同

Isolation.REPEATABLE_READ
    可重复读。这是MySQL的默认事务隔离级别
    解决了脏读,重读,但依然存在幻读问题。

Isolation.SERIALIZABLE
    可串行化
    最高的事务隔离级别。解决了脏读、重读、幻读
    但导致大量的超时和锁竞争。

Isolation.DEFAULT
    数据库默认隔离级别

只可读/可读写

有的事务不涉及到写操作,就可以将其指定为只读事务:@Transactional(readOnly=true),这样可以节约一些资源开销
默认是可读写

遇到哪些异常会回滚和不回滚----rollbackFor和noRollbackFor属性

默认在遇到RuntimeException的时候会回滚。

如果要指定在遇到checkedException的时候也回滚
    @Transactional(rollbackFor={IOException.class,FileNoteFoundException})
    多个异常类型,用数组

如果要指定遇到几个RuntimeException的时候不回滚
    @Transactional(noRollbackFor={NullPointerException.class,IndexOutOfBoundsException.class})
    多个异常类型,用数组
    测试的时候,抛出了Transaction rolled back because it has been marked as rollback-only,暂不知道原因


其他:
@Transaction应当添加在具体的实现类而不是接口上

posted @ 2017-03-20 20:12  sonng  阅读(8936)  评论(1编辑  收藏  举报