A.概念
1.事务的概念
事务是逻辑上一组操作,组成这组操作各个逻辑单元,要么一起成功,要么一起失败。
2.事务的特性
原子性
一致性
隔离性
持久性
如果不考虑隔离性,引发安全问题.
读问题
脏读
不可重复读
虚读
写问题
丢失更新
解决读问题:设置事务隔离级别
read uncommitted
read committed
repeatable read
Serializable
B. Spring事务管理的API
PlatformTransactionManager,是spring的平台事务管理器,它里面提供了我们常用的操作事务的方法.
开发中都是使用它的实现类
真正管理事务的对象
org.springframework.jdbc.datasource.DataSourceTransactionManager 使用Spring
JDBC或iBatis 进行持久化数据时使用
org.springframework.orm.hibernate3.HibernateTransactionManager 使用Hibernate版本进行持久化数据时使用
2.TransactionDefinition事务的定义信息对象
事务的隔离级别(重点)
.事务的传播行为(重点)
REQUIRED:如果当前没有事务,就新建一个事务,如果已经存在一个事务中,加入到这个事务中。一般的选择(默认值)
REQUERS_NEW:新建事务,如果当前在事务中,把当前事务挂起。
SUPPORTS:支持当前事务,如果当前没有事务,就以非事务方式执行(没有事务)
MANDATORY:使用当前的事务,如果当前没有事务,就抛出异常
NOT_SUPPORTED:以非事务方式执行操作,如果当前存在事务,就把当前事务挂起
NEVER:以非事务方式运行,如果当前存在事务,抛出异常
NESTED:如果当前存在事务,则在嵌套事务内执行。如果当前没有事务,则执行REQUIRED类似的操作。
超时时间
默认值是-1,没有超时限制。如果有,以秒为单位进行设置。
事务是否只读(重点)
建议查询时设置为只读。
TransactionStatus此接口提供的是事务具体的运行状态
小结:Spring框架进行事务的管理,首先使用TransactionDefinition对事务进行定义。通过PlatformTransactionManager根据TransactionDefinition的定义信息进行事务的管理。在事务管理过程中产生一系列的状态:保存到TransactionStatus中。
2.案例:转账
1 .搭建环境
建表
create database ee19_spring_day03;
use ee19_spring_day03;
create table account(
id int primary key auto_increment,
username varchar(50),
money int
);
insert into account(username,money) values('jack','10000');
insert into account(username,money) values('rose','10000');
导入jar包
核心:4+1
aop : 4 (aop联盟、spring aop、aspectj规范、spring aspect)
数据库:2 (jdbc/tx)
驱动:mysql
连接池:c3p0
dao层
interface : AccountDao
实现:
public class AccountDaoImpl extends JdbcDaoSupport implements AccountDao {
@Override
public void out(String outer, Integer money) {
this.getJdbcTemplate().update("update account set money = money - ? where username = ?", money,outer);
}
@Override
public void in(String inner, Integer money) {
this.getJdbcTemplate().update("update account set money = money + ? where username = ?", money,inner);
}
service层
public class AccountServiceImpl implements AccountService {
private AccountDao accountDao;
public void setAccountDao(AccountDao accountDao) {
this.accountDao = accountDao;
}
@Override
public void transfer(String outer, String inner, Integer money) {
accountDao.out(outer, money);
//断电
// int i = 1/0;
accountDao.in(inner, money);
}
}
AOP 配置基于xml
spring xml 配置aop 自动生成代理,进行事务的管理
1.配置管理器
2.配置事务详情
3.配置aop
<!-- 4 事务管理 -->
<!-- 4.1 事务管理器 -->
<bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"></property>
</bean>
<!-- 4.2 事务详情(事务通知) , 在aop筛选基础上,对ABC三个确定使用什么样的事务。例如:AC读写、B只读 等
<tx:attributes> 用于配置事务详情(属性属性)
<tx:method name=""/> 详情具体配置
propagation 传播行为 , REQUIRED:必须;REQUIRES_NEW:必须是新的
isolation 隔离级别
<tx:advice id="txAdvice" transaction-manager="txManager">
<tx:attributes>
<tx:method name="transfer" propagation="REQUIRED" isolation="DEFAULT"/>
</tx:attributes>
</tx:advice>
<!-- 4.3 AOP编程,目标类有ABCD(4个连接点),切入点表达式 确定增强的连接器,从而获得切入点:ABC -->
<aop:config>
<aop:advisor advice-ref="txAdvice" pointcut="execution(* com.itheima.service..*.*(..))"/>
</aop:config>
AOP配置基于注解
1.配置事务管理器,将并事务管理器交予spring
2.在目标类或目标方法添加注解即可 @Transactional
spring配置
<!-- 4 事务管理 -->
<!-- 4.1 事务管理器 -->
<bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"></property>
</bean>
<!-- 4.2 将管理器交予spring
* transaction-manager 配置事务管理器
* proxy-target-class
true : 底层强制使用cglib 代理
-->
<tx:annotation-driven transaction-manager="txManager"/>
在需要的地方(类或方法)加入注解@Transactional
例如:service 层
@Transactional
public class AccountServiceImpl implements AccountService {
事务详情配置
@Transactional(propagation=Propagation.REQUIRED , isolation = Isolation.DEFAULT)
public class AccountServiceImpl implements AccountService {