spring事务原理

1.  事务基本概念

    事务是指在数据库系统执行过程中的一个逻辑单元,由有限的数据库操作序列构成。

1.1 事务的基本特点

    事务具有四个属性:ACID本别是: 原子性(atomicity)、一致性(consistency)、隔离性(isolation)、持久性(durability)。

    原子性(要么成功要么失败):一个事务是不可分割的基本单位,事务中的所有操作要么要么全部都做,要么全部不做。

    一致性(数据库状态变化):事务必须使数据库从一个状态变化到另一个状态。一致性与原子性密切相关。

    隔离性(互不影响):一个事务的执行不能被其他事务干扰。不同的事务之间互补干扰。

    持久性(不能撤销):一个事务一旦提交,它对数据库中数据的改变就是永久性的。

2. 事务的基本原理

    spring事务的本质是对数据库事务的支持,没有数据库事务的支持,spring是无法提供事务功能的。

    对jdbc操作数据库要使用事务,使用如下步骤:

    (1) 获取连接 Connection con = DriverManager.getConnection(url,username,password);

    (2) 开启事务 con.setAutoCommit(false);

    (3) 执行数据库curd操作

    (4) 提交事务/回滚事务 con.commit()/con.rollback();

    (5) 关闭连接 conn.close();

    在是用spring的事务管理功能后,我们可以不用再写2和4的代码,而是由spring自动完成, 具体如何自动完成的,使用到了aop和动态代理的相关技术。

3. spring事务的传播特性

    spring事务的传播特性就是定义同时存在多个事务的时候,spring应该如何处理这些事务的行为。

    这些属性定义在TransactionDefinition中,具体常量解释如下:

常量名称常量解释
PROPAGATION_REQUIRED支持当前事务,如果当前没有事务就新建一个事务。这是最常见的选择,也是spring默认的事务的传播
PROPAGATION_REQUIRES_NEW新建事务,如果当前存在事务,就把当前事务挂起。新建的事务和被挂起的事务是两个独立的事务,外层事务失败回滚之后不能回滚内部事务执行的结果, 内存事务失败抛出异常,外层事务捕获,也可以不处理回滚操作。
PROPAGATION_SUPPORTS支持当前事务,如果当前没有事务,就以非事务的方式运行
PROPAGATION_NOT_SUPPORTED以非事务的方式运行,如果当前存在事务,就把当前事务挂起
PROPAGATION_MANDATORY支持当前事务,如果当前没有事务,就抛出异常
PROPAGATION_NEVER以非事务的方式运行,如果当前存在事务,就抛出异常
PROPAGATION_NESTED如果一个活动的事务存在,则运行在嵌套的事务中,如果没有活动的事务,则按PROPAGATION_REQUIRED执行。使用一个单独的事务,这个事务拥有多个可以回滚的事务保存点。

4. 数据库事务隔离级别      

    脏读: 在一个事务中读取到另一个事务未提交的数据。

    不可重复度:在一个事务中两次的查询结果不一样(针对update操作)。

    幻读:在一个事务中两次的查询结果不一样(正对insert操作)   

                            √ 可能出现 × 不会出现
隔离级别脏读不可重复读幻读
ISOLATION_READ_UNCOMMITED
ISOLATION_READ_COMMITED×
ISOLATION_REPEATABLE_READ××
ISOLATION_SERIALIZABLE×××

ISOLATION_READ_UNCOMMITED:事务最低的隔离级别,它允许另外一个事务看到当前事务未提交的数据。可能产生藏独、不可重复度、幻读。

ISOLATION_READ_COMMITED:另一个事务不能读取当前事务未提交的数据。

ISOLATION_REPEATABLE_READ:防止了脏读、不可重复读出现,但是可能出现幻读。

ISOLATION_SERIALIZABLE:防止了脏读、不可重复读、幻读,可靠性最好的事务级别,但是执行效率也是最慢的,慎用。

数据库隔离级别越高,越能保证数据的完整性和一致性,但是对并发性能的影响也越大。多数数据的默认隔离级别都是read commited,如sqlServer,oracle;少数数据库隔离级别默认是repeatable read,如mysqlInnoDB。

5. spring中的事务隔离级别

ISOLATION_DEFAULTspring默认的隔离级别,使用数据库默认的隔离级别
ISOLATION_READ_UNCOMMITED同数据库事务隔离级别
ISLATION_READ_COMMITED同数据库事务隔离级别
ISOLATION_REPEATABLE_READ同数据库事务隔离级别
ISOLATION_SERIALIZEABLE同数据库事务隔离级别

6. 举例说明事务的嵌套,理解spring事务传播机制

假设外层事务serviceA的methodA()方法调用内层的serviceB的methodB()方法

PROPAGATION_REQUIRED

如果serviceB.methodB()的事务定义为PROPAGATION_REQUIRED,如果servieA.methodA()执行的时候已经开启了事务,那么serviceB.methodB()在执行的时候发现已经在methodA的事务中,那么就不会再新建一个事务;如果methodA()没有在事务中,那么methodB()在执行的时候就会新建一个事务。这样在methodA()和methodB()中的任何地方出现异常,事务都会回滚,即使被methodA中catch住,也会因为是一个事物在methodB的时候标记为事物失败而抛出一个UnexpectedRollbackException(org.springframework.transaction.UnexpectedRollbackException: Transaction rolled back because it has been marked as rollback-only)导致回滚。

PROPAGATION_REQUIRES_NEW

执行到method()的时候,methodA()所在的事务就会挂起,methodB()会新开启一个事务,methodB()所在的事务执行完以后method所在的事务才会继续执行。它与PROPAGATION_REQUIRED的区别在于回滚的程度。因为B是新起的一个事务,如果B已经提交,A失败回滚,那么B也是不会回滚; 如果B失败回滚,抛出的异常被A捕获(try catch住),如果在catch中没有抛出异常,那么A不会回滚;如果catch中抛出异常并且是A上rollbackFor设置的异常,则回滚,如果不是,则不会回滚。

serviceA#methodA() -> serviceB#methodB()

如果methodB() 抛出异常,在methodA()中try catch住,如果没有重新抛出或者抛出的异常不是methodA方法rollbackFor设置的异常,那么 methodA 不会滚,methodB回滚;

如果methodB()抛出异常,在methodA()中try catch住,并且重新抛出了methodA上rollbackFor设置的异常,那么methodA回滚,methodB回滚;

如果methodB()抛出异常,在methodA()中没有try catch住,那么methodA methodB都会回滚;

如果只有methodA抛出异常,那么methodA回滚,methodB不会滚

PROPAGATION_NESTED

serviceA#methodA() -> serviceB#methodB()

如果methodB()抛出异常,如果在methodA中catch处理,那么methodA不会滚,methodB回滚;如果methodA没有catch处理,那么methodA,methodB都回滚

如果methodA()抛出异常,那么methodA,methodB都回滚。

7. 对于同一个类中事物方法调用失效的情况处理

首先需要设置exposeProxy=true, 通过xml方式或者注解方式:<aop:aspectj-autoproxy proxy-target-class="true" expose-proxy="true" /> 或者 @EnableAspectJAutoProxy(exposeProxy=true)

调用:((UserService)AopContext.currentProxy()).testExpose1();

 

 

 

 

 

 

 

 

 

 

转载于:https://my.oschina.net/u/1987615/blog/3074141

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值