Spring的基础和应用系列文章目录
第一部分 Spring 基础
1.1 XML使用-IoC配置与依赖(DI)配置
1.2 基于注解和XML混合方式的使用
1.3 基于纯注解方式的使用
1.4 AOP 介绍
1.5 Spring 整合AspectJ的AOP使用
第二部分 组件支持
2.1 Spring 整合Junit
2.2 Spring 事务支持
Spring 事务支持
一 事务回顾
1.1 事务介绍
事务:指的是逻辑上一组操作,组成这个事务的各个执行单元,要么一起成功,要么一起失败!
事务的特性(ACID):以下只是本地事务,事务是数据库实现的。spring 只是设置些参数。
- 原子性(Atomicity)
原子性是指事务包含的所有操作要么全部成功,要么全部失败回滚。 - 一致性(Consistency)
一致性是指事务必须使数据库从一个一致性状态变换到另一个一致性状态,也就是说一个事务执行之前和执行之后都必 须处于一致性状态。 拿转账来说,假设用户A和用户B两者的钱加起来一共是5000,那么不管A和B之间如何转账,转几次账,事务结束后两 个用户的钱相加起来应该还得是5000,这就是事务的一致性。 - 隔离性(Isolation)
隔离性是当多个用户并发访问数据库时,比如操作同一张表时,数据库为每一个用户开启的事务,不能被其他事务的操 作所干扰,多个并发事务之间要相互隔离。 - 持久性(Durability)
持久性是指一个事务一旦被提交了,那么对数据库中的数据的改变就是永久性的,即便是在数据库系统遇到故障的情况 下也不会丢失提交事务的操作。
1.2 事务并发问题(隔离性导致)
在事务的并发操作中可能会出现一些问题:
- 脏读:一个事务读取到另一个事务未提交的数据。
- 不可重复读:一个事务因读取到另一个事务已提交的数据。导致对同一条记录读取两次以上的结果不一致。update操作
- 幻读:一个事务因读取到另一个事务已提交的数据。导致对同一张表读取两次以上的结果不一致。insert、 delete操作
1.3 事务隔离级别
为了避免上面出现的几种情况,在标准SQL规范中,定义了4个事务隔离级别,不同的隔离级别对事务的处理不同
-
四种隔离级别:
现在来看看MySQL数据库为我们提供的四种隔离级别(由低到高):
① Read uncommitted (读未提交):最低级别,任何情况都无法保证。
② Read committed (读已提交):可避免脏读的发生。
③ Repeatable read (可重复读):可避免脏读、不可重复读的发生。
④ Serializable (串行化):可避免脏读、不可重复读、幻读的发生。 -
默认隔离级别
大多数数据库的默认隔离级别是Read Committed(RC),比如Oracle、DB2等。
MySQL数据库的默认隔离级别是Repeatable Read(RR)。
隔离级别越高,越能保证数据的完整性和一致性,但是对并发性能的影响也越大。
1.4 Spring框架事务管理相关接口
Spring并不直接管理事务,而是提供了事务管理接口是PlatformTransactionManager,通过这个接口,Spring 为各个平台如JDBC、Hibernate等都提供了对应的事务管理器,但是具体的实现就是各个平台自己的事情了。
- PlatformTransactionManager接口 – 平台事务管理器.(真正管理事务的类)。该接口有具体的实现类,根据不同的持久层框架,需要选择不同的实现类!
- TransactionDefinition接口 – 事务定义信息.(事务的隔离级别,传播行为,超时,只读)
- TransactionStatus接口 – 事务的状态(是否新事务、是否已提交、是否有保存点、是否回滚)
总结:上述对象之间的关系:平台事务管理器真正管理事务对象.根据事务定义的信息
TransactionDefinition 进行事务管理,在管理事务中产生一些状态.将状态记录到TransactionStatus中
1.4.1 PlatformTransactionManager接口中实现类和常用的方法
- 接口的实现类 * 如果使用的Spring的JDBC模板或者MyBatis(IBatis)框架,需要选择DataSourceTransactionManager 实现类* 如果使用的是Hibernate的框架,需要选择HibernateTransactionManager实现类
- 该接口的常用方法 * void commit(TransactionStatus status) * TransactionStatus getTransaction(TransactionDefinition definition) * void rollback(TransactionStatus status)
1.4.2 TransactionDefinition
- 事务隔离级别的常量
static int ISOLATION_DEFAULT – 采用数据库的默认隔离级别
static int ISOLATION_READ_UNCOMMITTED
static int ISOLATION_READ_COMMITTED
static int ISOLATION_REPEATABLE_READ
static int ISOLATION_SERIALIZABLE - 事务的传播行为常量(不用设置,使用默认值)
先解释什么是事务的传播行为:解决的是业务层之间的方法调用!!- PROPAGATION_REQUIRED
(默认值) – A中有事务,使用A中的事务.如果没有,B就会开启一个新 的事务,将A包含进来.(保证A,B在同一个事务中),默认值!! - PROPAGATION_SUPPORTS
A中有事务,使用A中的事务.如果A中没有事务.那么B也不使用事务. - PROPAGATION_MANDATORY
A中有事务,使用A中的事务.如果A没有事务.抛出异常. - PROPAGATION_REQUIRES_NEW
A中有事务,将A中的事务挂起.B创建一个新的事务.(保证 A,B没有在一个事务中) - PROPAGATION_NOT_SUPPORTED – A中有事务,将A中的事务挂起.
- PROPAGATION_NEVER – A中有事务,抛出异常.
- PROPAGATION_NESTED
嵌套事务.当A执行之后,就会在这个位置设置一个保存点. 如果B没有问题.执行通过.如果B出现异常,运行客户根据需求回滚(选择回滚到保存点或者是最初始状态)
- PROPAGATION_REQUIRED
二、Spring框架事务管理的分类
2.1 编程式事务管理(了解)
说明:Spring为了简化事务管理的代码:提供了模板类 TransactionTemplate,所以手动编程的方式来管理事务,只需要使用该模板类即可!!
手动编程方式的具体步骤如下:
- List item配置一个事务管理器,Spring使用PlatformTransactionManager接口来管理事务,所以咱们需要使用到他的实现类!!
<!-- 配置事务管理器 -->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"></property>
</bean>
- 配置事务管理的模板
<!-- 配置事务管理的模板 -->
<bean id="transactionTemplate" class="org.springframework.transaction.support.TransactionTemplate">
<property name="transactionManager" ref="transactionManager"/>
</bean>
- 在需要进行事务管理的类中,注入事务管理的模板
<bean id="accountService" class="com.kkb.spring.service.AccountServiceImpl">
<property name="accountDao" ref="accountDao"/>
<property name="transactionTemplate" ref="transactionTemplate"/>
</bean>
- 在业务层使用模板管理事务
// 注入事务模板对象 private TransactionTemplate transactionTemplate;
public void setTransactionTemplate(TransactionTemplate transactionTemplate) {
this.transactionTemplate = transactionTemplate;
}
public void pay(final String out, final String in, final double money) {
transactionTemplate.execute(new TransactionCallbackWithoutResult() {
protected void doInTransactionWithoutResult(TransactionStatus status) {
// 扣钱
accountDao.outMoney(out, money);
int a = 10 / 0;
// 加钱
accountDao.inMoney(in, money);
}
});
}
2.2.2 声明式事务管理
见下节详解
三、 声明式事务管理(重点)
3.1 事务管理之XML方式
准备转账环境:业务层AccountService和 持久层AccountDao .
配置事务管理的AOP
平台事务管理器:DataSourceTransactionManager, 配置数据源,数据源是访问数据库的配置。
<!-- 配置数据源 -->
<bean id="dataSource"
class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName"
value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql:///kkb"/>
<property name="username" value="root"/>
<property name="password" value="root"/>
</bean>
<!--配置AccountService和AccountDao -->
<context:component-scan base-package="com.kkb.spring.tx"></context:component-scan>
<!-- 配置事务管理器 -->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"></property>
</bean>
事务通知:
tx:attributes 事务的属性, method 切入点业务代码中的方法名。
<!-- 配置事务通知类(Spring实现的事务增强类) -->
<!-- TransactionInterceptor -->
<tx:advice id="txAdvice"
transaction-manager="transactionManager">
<tx:attributes>
<tx:method name="save*" propagation="REQUIRED" />
<tx:method name="update*" propagation="REQUIRED" />
<tx:method name="transfer*" propagation="REQUIRED" />
<tx:method name="query*" read-only="true" />
</tx:attributes>
</tx:advice>
AOP配置:
使用了Spring AOP 的实现。advice-ref=“txAdvice” 指定通知类。
<!-- 配置aop切面类或者通知器类 -->
<aop:config>
<!-- 这使用的是Spring AOP的实现 -->
<!-- advice-ref:指定advice增强类 -->
<aop:advisor advice-ref="txAdvice"
pointcut="execution(* *..*.*ServiceImpl.*(..))" />
</aop:config>
3.2 事务管理之混合方式
-
service类上或者方法上加注解:
类上加@Transactional:表示该类中所有的方法都被事务管理
方法上加@Transactional:表示只有该方法被事务管理 -
开启事务注解:
<!-- 配置事务管理器 -->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"></property>
</bean>
<!-- 配置事务注解驱动 -->
<tx:annotation-driven transaction-manager="transactionManager"/>
3.3 事务管理之基于AspectJ的纯注解方式
@EnableTransactionManagement