Spring的事务实现及细节处理

一、Spring实现事务

  1.eclipse在当前项目的lib中添加spring-aspects-4.3.10.RELEASE.jar包

  2.在application.xml中添加<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager" p:id="dataSource"></bean>(配置事务管理器)

  <tx:annotation-driven transaction-manager="transactionManager"/>(添加事务注解)

  (配置事务管理器意味着C语言的定义变量,添加事务注解意味着使用这个变量

  3.将test类中的getBean方法中的service.class转换成对应接口.class(动态代理),再在service类中的对应方法中添加注释@Transactional

二、注释@Transactional中的属性含义

  1.readOnly(只读)

这个属性默认值为false,即表示该方法中的事务可以有查询,更新,添加和删除,而更改为true时只能查询,当添加其他sql语句运行时会自动报错 

  (报错详细原因为:Exception in thread "main" org.springframework.dao.TransientDataAccessResourceException: PreparedStatementCallback; SQL [update book set quantity = quantity- 2 where id=?]; Connection is read-only. Queries leading to data modification are not allowed; nested exception is java.sql.SQLException: Connection is read-only. Queries leading to data modification are not allowed)

  2.timeout

这个属性表示方法中的事务运行的最大时间限制,一般为无穷大,设置一定值后,若此事务运行时间超过这个定值,则事务自动回滚且报错。(一般timeout对应值的单位是秒,而Thread.sleep方法里的值的单位是毫秒,使用时需要转换) 

​​​并且需要注意事务执行时通常会锁住对应表的一行或整列信息,运行时间过长会影响系统运行,需要设置时限,同时由于超时是在一个事务启动的时候开始的,因此,只有对于那些具有可能启动一个新事务的传播行(PROPAGATION_REQUIRES_NEW、PROPAGATION_REQUIRED、ROPAGATION_NESTED)的方法来说,声明事务超时才有意义。​​​ 

  3.rollbackFor和rollbackForClassName

指定对哪些异常回滚事务,不过rollbackFor对应多个,rollbackForClassName对应单个。其中默认设置为运行时异常,即检查时异常相当于没有异常会让事务仍然提交,当设置为对应检查时异常的class时,则该检查时异常也会让事务回滚(此时异常处理方法必须为抛出,不能使用try、catch,否则检查时异常也仍然会提交),同样还有属性noRollbackFor和noRollbackForClassName,​​​​​不过其含义​与rollbackFor和rollbackForClassName相反,为指定对哪些异常不回滚事务。  默认情况下,钱不够的异常为运行时异常,事务回滚 当修改为检查时异常,事务提交当添加MoneyException为指定异常回滚事务,事务回滚,此时采用throws MoneyException抛出异常

当改为try catch捕获异常即未抛出异常时,事务提交

 

  4.propagation

指定事务传播行为,一个事务方法被另一个事务方法调用时,必须指定事务应该如何传播。一般默认值为REQUIRED,即有事务时此方法在这个事务里运行,没有则创建新事务;另一个常用值为REQUIRED_NEW,与REQUIRED相反,不管是否有事务,直接创建新事务,且此事务优先级在旧事务之上,即此事务回滚或提交后旧事务执行。

此时insert事务方法在batch事务中运行

此时insert事务方法创建新事务并在执行后才继续执行batch事务方法当两或两个以上事务方法在同一个类里面时,无论propagation值为多少,它们传递时都在同一个事务里。

SUPPORTS:如果有事务在运行,当前的方法就在这个事务内运行,否则以非事务的方式运行;

NOT_SUPPORTED:当前的方法不应该运行在事务中,如果有运行的事务,则将它挂起;

NEVER:当前方法不应该运行在事务中,否则将抛出异常;

MANDATORY(mandatory [ˈmændətɔːri] adj.强制的):当前方法必须运行在事务内部,否则将抛出异常;

NESTED(nest [nest] v.嵌套):如果有事务在运行,当前的方法在这个事务的嵌套事务内运行,否则就启动一个新的事务,并在它自己的事务内运行,此时等价于REQUIRED。注意:对于NESTED内层事务而言,内层事务独立于外层事务,可以独立递交或者回滚,如果内层事务抛出的是运行异常,外层事务进行回滚,内层事务也会进行回滚。

 

  5.isolation

指定事务隔离级别,Spring定义了如下5种事务隔离级别:

DEFAULT:默认值,表示使用底层数据库的默认隔离级别。对大部分数据库而言,通常为READ_COMMITTED。

READ_UNCOMMITTED:表示一个事务可以读取另一个事务修改但还没有提交的数据。该级别可能出现脏读、不可重复读或幻读,因此很少使用该隔离级别。

脏读:已知有两个事务AB, A读取了已经被B更新但还没有被提交的数据,之后,B回滚事务,A读取的数据就是脏数据。

READ_COMMITTED:表示一个事务只能读取另一个事务已经提交的数据。该级别可以防止脏读,但可能出现不可重复读或幻读,这也是大多数情况下的推荐值。

不可重复读:已知有两个事务ABA 多次读取同一数据,B A多次读取的过程中对数据作了修改并提交,导致A多次读取同一数据时,结果不一致

REPEATABLE_READ:表示一个事务在整个过程中可以多次重复执行某个查询,且每次返回的记录都相同,除非数据被当前事务自生修改。即使在多次查询之间有新增的数据满足该查询,这些新增的记录也会被忽略。该级别可以防止脏读和不可重复读,但可能出现幻读。

幻读:已知有两个事务ABA从一个表中读取了数据,然后B在该表中插入了一些新数据,导致A再次读取同一个表, 就会多出几行,简单地说,一个事务中先后读取一个范围的记录,但每次读取的纪录数不同,称之为幻象读

SERIALIZABLE:表示所有的事务依次逐个执行,事务之间互不干扰,该级别可以防止脏读、不可重复读和幻读,但是这将严重影响程序的性能,因此通常情况下也不会用到该级别。

事务的隔离级别要得到底层数据库引擎的支持, 而不是应用程序或者框架的支持:Oracle 支持READ_COMMITED和SERIALIZABLE两种事务隔离级别,默认为READ_COMMITED;MySQL 支持READ_UNCOMMITTED、READ_COMMITTED、REPEATABLE_READ和SERIALIZABLE四种事务隔离级别,默认为:REPEATABLE_READ。

注意:当isolation值为REPEATABLE_READ时,由于MVCC原理而使幻读情况中A再次读同一个表而导致快照读而“消灭”幻读,实际上B仍然在A查询间隔在表中插入了数据,只不过A不能读到当前表而已 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值