1.spring事务管理高层抽象主要有三个接口,spring的事务只要是由他们共同完成
- platformtransactionmanager:事务管理器—主要用于平台相关事务的管理
- transactiondefinition:事务定义信息(隔离,传播,超时,只读)—通过配置进行事务管理
- transactionstatus:事务具体运行状态—事务管理过程中,每个时间点,事务的状态信息
1.1 platformtarnsactionmanager事务管理器
该接口提供三个方法:
- commit:提交事务
- rollback:回滚事务
- gettransaction:获取事务状态
1.2 transactiondefinition事务定义信息
用来定义事务相关的属性,给事务管理器用
该接口主要提供的方法是:
- getlsolationlevel:隔离级别获取
- getpropagationbehavior:传播行为获取
- gettiomeout:获取超时时间
- isreadonly:是否只读(保存,更新,删除—对数据进行操作—变成可读写的,查询—设置这个属性为true,只能读,不能写)
这些事务的定义信息,都可以在配置文件中配置和定制
1. 脏读 :脏读就是指当一个事务正在访问数据,并且对数据进行了修改,而这种修改还没有提交到数据库中,这时,另外一个事务也访问这个数据,然后使用了这个数据。
2. 不可重复读 :是指在一个事务内,多次读同一数据。在这个事务还没有结束时,另外一个事务也访问该同一数据。那么,在第一个事务中的两 次读数据之间,由于第二个事务的修改,那么第一个事务两次读到的的数据可能是不一样的。这样就发生了在一个事务内两次读到的数据是不一样的,因此称为是不 可重复读。例如,一个编辑人员两次读取同一文档,但在两次读取之间,作者重写了该文档。当编辑人员第二次读取文档时,文档已更改。原始读取不可重复。如果 只有在作者全部完成编写后编辑人员才可以读取文档,则可以避免该问题。
3. 幻读 : 是指当事务不是独立执行时发生的一种现象,例如第一个事务对一个表中的数据进行了修改,这种修改涉及到表中的全部数据行。 同时,第二个事务也修改这个表中的数据,这种修改是向表中插入一行新数据。那么,以后就会发生操作第一个事务的用户发现表中还有没有修改的数据行,就好象 发生了幻觉一样。例如,一个编辑人员更改作者提交的文档,但当生产部门将其更改内容合并到该文档的主复本时,发现作者已将未编辑的新材料添加到该文档中。 如果在编辑人员和生产部门完成对原始文档的处理之前,任何人都不能将新材料添加到文档中,则可以避免该问题。
l DEFAULT 使用数据库设置的隔离级别 ( 默认 ) ,由 DBA 默认的设置来决定隔离级别 .
l READ_UNCOMMITTED 会出现脏读、不可重复读、幻读 ( 隔离级别最低,并发性能高 )
l READ_COMMITTED 会出现不可重复读、幻读问题(锁定正在读取的行)
l REPEATABLE_READ 会出幻读(锁定所读取的所有行)
l SERIALIZABLE 保证所有的情况不会发生(锁表)
不可重复读的重点是修改 :
同样的条件 , 你读取过的数据 , 再次读取出来发现值不一样了
幻读的重点在于新增或者删除
同样的条件 , 第 1 次和第 2 次读出来的记录数不一样
事务传播行为用于解决两个被事务管理的方法互相调用问题 业务层两个方法面临的事务问题: 有些时候需要处于同个事务(除用户删除完成之后,需要同时删除用户对应的订单,需要事务回滚,例如商场工作人员删除订单业务) 有些时候不能在同个事务(取款是一个事务操作,打印凭条是一个事务操作,例妙如ATM取款业务)!
事务传播七种类型:
事务传播行为类型 | 说明 |
---|---|
PROPAGATION_REQUIRED | 支持当前事务,如果当前没有事物,就新建一个事务;如果有事物,就直接使用当前前事物、 |
PROPAGATION_SUPPORTS | 如果当前没有事务,就以非事务方式执行、 |
PROPAGATION_MANDATORY | 如果当前没有事务,就抛出异常。 |
PROPAGATION_REQUIRES_NEW | 不支持当前事务,如果当前有事物,就将当前前事物挂起,新建一个事物、 |
PROPAGATION_NOT_SUPPORTED | 如果有事务,就将当前前事物挂起,并以非事务方式执行 |
PROPAGATION_NEVER | 如果有事物,就抛异常,即必须以非事务方式执行 |
PROPAGATION_NESTED | 奇葩类型:支持当前事物的特例,如果有事物,也新建一个事务,以事务嵌套事物的方式执行。 |
REQUIRED,REQUIRES_NEW,NESTED区分
REQUIRED:只有要给事务(默认,推荐)
REQUIRES_NEW:存在两个事务,如果事务存在,挂起事务,重新又开启了一个新的事务
NESTED嵌套事务,事务可以设置保存点,回滚到保存点,选择提交或者回滚。
1.3 transactionstatus事务状态
hassavepoint():判断是否有保留点
iscompleted():判断事务是否结束
isnewtransaction():判断当前事务是否是新开的一个事务
isrollbackonly():判断事务是否只能回滚
setrollbackonly():设置事务是否回滚
事物的结束:必须通过commit确认事务提交,rollback作用标记为回滚
数据库操作中,如果只是回滚,后面不操作,数据库在关闭连接的时候,自动发出了commit
三个事务超级接口对象之间的关系
1)首先用户管理事务,需要先配置 Transactionmanager(事务管理噐)进行事务管理
2)然后根据 Transaction Definition(事物定义信息),通过 Transactionmanager(事务管理器)进行事务管理
3)最后事务运行过程中,每个时刻都可以通过获取 Transactionstatus(事务状态)来了解事务的运行状态。
1.4 spring事务管理两种方式
- 编程式事务管理
通过transaction template手动管理事务,实际应用很少使用,因为要修改源代码,加入事务管理代码,具有侵入性。 - 使用xml或者注解配置声明式事务
spring的声明式事务是通过aop实现的(环绕通知)
开发中常使用,侵入性小。
事务管理操作思路:- 确立目标,需要对什么方法配置切入点
- 需要设置什么,比如advice(环绕通知),方法前开启事务,方法后关闭事务
- 配置切面和切入点
<bean id="transactionmanager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="datasource"></property>
</bean>
<!--配置事务通知-->
<!-- transaction-manager:指定事务管理器的id,如果事务管理器的id为transactionmanager,该属性可以省略-->
<tx:advice id="txadvice" transaction-manager="transactionmanager">
<tx:attributes>
<tx:method name="transfer" isolation="DEFAULT" propagation="REQUTRED"
read-only="false" timeout="-1"></tx:method>
</tx:attributes>
</tx:advice>
<!-- 配置切入点和切面-->
<aop:config>
<aop:pointcut id="mycut" expression="bean(*service)"/>
<aop:advisor advice-ref="txadvice" pointcut-ref="mycut"></aop:advisor>
</aop:config>
如果用注解,只需一个@transactional足矣~
小结
xml:集中式维护,统一放到applicationcontext.xml中,缺点在于配置文件中内容过多
使用@transactional注解进行配置太分散,使用xml便于管理
以后的service方法名字的命名,必须是以上规则,否则不可以被spring管理,以save,updata,delete开头的方法,表示增删改的操作,事务务必为可写。