一、Spring中的AOP事务
1.1 事务
1.1.1 事务特性ACID
- 原子性(Atomicty)
- 一致性(Consistency)
- 隔离性(Isolation)
- 持久性(Durability)
1.1.2 事务并发问题
- 脏读
- 不可重复读
- 幻读
1.1.3 事务的隔离级别
- 读未提交:1
- 读已提交:2
- 可重复读:4
- 串行化:8
二、Spring中的事务管理
2.1 事务操作
- 打开事务
- 提交事务
- 回滚事务
2.2 事务操作对象
- 不同平台操作事务的代码都不一样,因此Spring提供了一个接口。
PlatformTransactionManager
接口。
2.3 !!PlatformTransactionManager接口
- Spring中事务管理,最为核心的对象就是
TransactionManager
对象
2.3.1 DataSourceTransactionManager
2.3.2 HibernateTransactionManager
2.4 Spring管理事务的属性介绍
2.4.1 事务的隔离级别
- 读未提交:1
- 读已提交:2
- 可重复读:4
- 串行化:8
2.4.2 是否只读
true
:只读false
:可操作
2.4.3 事务的传播行为
PROPAGATION_REQUIRED
:支持当前事务,如果不存在,就新建一个(<font color="red">默认</font>)PROPAGATION_SUPPORTS
:支持当前事务,如果不存在,就不使用事务。PROPAGATION_MANDATORY
:支持当前事务,如果不存在,抛出异常。PROPAGATION_REQUIRES_NEW
:如果有事务存在,挂起当前事务,创建一个新的事务PROPAGATION_NOT_SUPPORTED
:以非事务方式运行,㘝有事务存在,挂起当前事务。PROPAGATION_NEVER
:以非事务方式运行,如果有事务存在,抛出异常PROPAGATION_NESTED
:如果当前事务存在,则嵌套事务执行
三、Spring管理事务方式
- 原理图
3.1 xml配置(aop)
3.1.1 导包
- aop
- aspect
- aop-alliance
- aop-weaver
3.1.2 导入新的约束(tx)
- beans:最基本
- context:读取properties配置
- aop:配置aop
- tx:配置事务通知
3.1.3 配置通知
<!-- 0.注册dataSource -->
<bean name="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="driverClass" value="com.mysql.jdbc.Driver"></property>
<property name="jdbcUrl" value="jdbc:mysql:///ssh"></property>
<property name="user" value="root"></property>
<property name="password" value="123456"></property>
</bean>
<!-- 1.注册事务管理的核心对象 - 通知类 -->
<bean name="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"></property>
</bean>
<!-- 2.配置事务管理的具体通知属性,需要添加新的命名空间tx
隔离级别、只读性、传播行为
transaction-manager:可以省略,自动找transactionManager对象
-->
<tx:advice id="tx" transaction-manager="transactionManager">
<tx:attributes>
<tx:method name="transfer" isolation="REPEATABLE_READ" propagation="REQUIRED" read-only="false"/>
<tx:method name="get*" isolation="REPEATABLE_READ" propagation="REQUIRED" read-only="true"/>
<tx:method name="find*" isolation="REPEATABLE_READ" propagation="REQUIRED" read-only="true"/>
<tx:method name="save*" isolation="REPEATABLE_READ" propagation="REQUIRED" read-only="false"/>
<tx:method name="presist*" isolation="REPEATABLE_READ" propagation="REQUIRED" read-only="false"/>
<tx:method name="update*" isolation="REPEATABLE_READ" propagation="REQUIRED" read-only="false"/>
<tx:method name="modify*" isolation="REPEATABLE_READ" propagation="REQUIRED" read-only="false"/>
<tx:method name="delete*" isolation="REPEATABLE_READ" propagation="REQUIRED" read-only="false"/>
<tx:method name="remove*" isolation="REPEATABLE_READ" propagation="REQUIRED" read-only="false"/>
</tx:attributes>
</tx:advice>
<!-- 3.aop织入 -->
<aop:config>
<aop:pointcut expression="execution(* d_transaction.*ServiceImpl.*(..))" id="pc"/>
<aop:advisor advice-ref="tx" pointcut-ref="pc"/>
</aop:config>
3.1.4 配置将通知织入目标
- 见是上第三步!
3.2 注解配置(aop)
3.2.1 导包(同xml)
3.2.2 导入新的约束tx(同上)
3.2.3 开启注解管理事务
记得开注解包扫描
<context:component-scan base-package="d_transaction_annotation"></context:component-scan>
记得开启使用注解管理aop事务
- `<tx:annotation-driven transaction-manager="transactionManager"/>
</beans>`
- `<tx:annotation-driven transaction-manager="transactionManager"/>
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://www.springframework.org/schema/beans"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.3.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.3.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.3.xsd">
<!-- 1.开启注解包扫描 @Service @Controller @Repository @Component -->
<context:component-scan base-package="d_transaction_annotation"></context:component-scan>
<!-- 2.注册dao -->
<bean name="accountDao" class="d_transaction_annotation.AccountDaoImpl">
<property name="dataSource" ref="dataSource"></property>
</bean>
<!-- 1.引入src/db.properties配置文件 -->
<context:property-placeholder location="classpath:db.properties"/>
<!-- 3.注册dataSource -->
<bean name="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="driverClass" value="${jdbc.driverClass}"></property>
<property name="jdbcUrl" value="${jdbc.jdbcUrl}"></property>
<property name="user" value="root"></property>
<property name="password" value="123456"></property>
</bean>
<!-- 1.注册事务管理的核心对象 - 通知类 -->
<bean name="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"></property>
</bean>
<!-- 使用注解来配置事务的属性以及织入
@Transactional
-->
<tx:annotation-driven transaction-manager="transactionManager"/>
</beans>
3.2.4 使用注解
@Transactional(isolation = Isolation.REPEATABLE_READ, propagation = Propagation.REQUIRED, readOnly = false)
package d_transaction_annotation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
@Service
// 对类中所有方法生效
@Transactional(isolation = Isolation.REPEATABLE_READ, propagation = Propagation.REQUIRED, readOnly = true)
public class AccountServiceImpl implements AccountService {
@Autowired
private AccountDao ad;
@Override
// 转账业务
// 对当前方法生效
@Transactional(isolation = Isolation.REPEATABLE_READ, propagation = Propagation.REQUIRED, readOnly = false)
public void transfer(int fromId, int toId, double money) {
// 减钱
ad.decrement(fromId, money);
// int a = 1/0;
// 加钱
ad.increment(toId, money);
}
}