事务基本特性
原子性:一个事务内的操作要成功都成功,要失败都失败。比如转账案例,转账和到账要么同时成功要么同时失败。
一致性:一致性和原子性描述的是同一件事,只不过角度不一样。原子性是从一个事务内的操作的角度来说的,要成都成要失败都失败。一致性是从数据的角度来说的,比如转账,转账的初始数据状态(1000,1000),现在转100块,转账完成后,对外来说,数据状态要么(900,1100),要么是(1000,1000),不能够出现(900,1000)等中间状态
隔离性:比如事务1给员工涨工资2000元,但是事务1尚未提交事务,事务2查询工资,发现工资涨了2000块。这就是脏读(读到了未提交的数据)
持久性:事务一旦提交即生效,即使数据库服务器宕机,那么重启之后数据也应该是事务提交之后的状态,不会是之前的状态
事务隔离级别
读未提交(极端) :Read Uncommited,读到了未提交的数据,什么并发问题也解决不了。不要采取这种方案
读已提交 :Read Committed:解决脏读问题,解决不了幻读和不可重复读的问题(因为幻读和不可重复读问题的造成,本身就是已提交事务造成的)
可重复读 :Read Repeatable,解决脏读和不可重复读的问题。解决不了幻读问题,因为可重复读针对的是update操作,在可重复读机制下,会对要update的语句进行加锁,加锁状态下其他事务无法修改。但是其他事务可以对表新增和删除
串行化(极端) :Serializable,事务一个个来,是最安全的隔离机制,但是效率较低,比如ATM机。
默认,数据库的默认,mysql默认的隔离机制是可重复读,Oracle的默认隔离机制
事务传播行为
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>5.0.2.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
<version>5.0.2.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>5.0.2.RELEASE</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.8.9</version>
</dependency>
事务管理器,就是关于事务的横切逻辑,我们使用jdbc/jdbcTemplate/mybatis使用的是Spring提供的DataSourceTransactionMannager事务管理类,这个类就如同自定义AOP中开发的TransactionMannager类
注意:
Spring DataSourceTransactionManager事务管理器仅jdbc/Spring JdbcTemplate工具和Mybatis。不支持Dbutils的事务管理
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx.xsd
">
<context:component-scan base-package="com.ujiuye.spring"/>
<!--配置文件的位置-->
<context:property-placeholder location="classpath:db.properties"/>
<!--定义jdbcTemplate对象-->
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource" ref="dataSource"/>
</bean>
<!--Spring的声明式事务是基于AOP技术实现
横切逻辑单独定义为一个bean
事务管理器底层还需要数据库连接池的支持
-->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/>
</bean>
<tx:advice id="txAdvice" transaction-manager="transactionManager">
<!--tx:attributes允许我们对事务细节进行配置-->
<tx:attributes>
<!--CRUD中只有查询是只读事务,其他都是非只读事务
所以在这里可以首先配置所有方法都是非只读事务
然后单独配置查询方法为只读事务,覆盖上面的配置
这样,简化配置量
read-only:是否只读
propagation [ˌprɒpə'ɡeɪʃ(ə)n]:事务传播行为
isolation [ˌaɪsəˈleɪʃn] :事务隔离级别,默认defalut
timeout:超时时间,-1没有限制,单位秒
rollback-for:出现什么异常的时候回滚事务,往往不需要配置,有异常就回滚
no-rollback-for:出现什么异常的时候不回滚事务,往往不需要配置,有异常就回滚
-->
<tx:method name="*" read-only="false" propagation="REQUIRED" isolation="DEFAULT" timeout="-1" />
<!--查询操作为只读事务即可,事务传播行为为SUPPORTS,有事务就用,没有就不用-->
<tx:method name="query*" read-only="true" propagation="SUPPORTS"/>
</tx:attributes>
</tx:advice>
<aop:config>
<!--Spring声明式事务使用aop:advisor替代aop中的aop:aspect
至于方位信息不需要指定了(对于事务来说)
-->
<aop:advisor advice-ref="txAdvice" pointcut="execution(* com.ujiuye.spring.service.*.*(..))"/>
</aop:config>
</beans>