一、Spring中的AOP事务

1.1 事务

1.1.1 事务特性ACID

  1. 原子性(Atomicty)
  2. 一致性(Consistency)
  3. 隔离性(Isolation)
  4. 持久性(Durability)

1.1.2 事务并发问题

  1. 脏读
  2. 不可重复读
  3. 幻读

1.1.3 事务的隔离级别

  • 读未提交:1
  • 读已提交:2
  • 可重复读:4
  • 串行化:8

二、Spring中的事务管理

2.1 事务操作

  1. 打开事务
  2. 提交事务
  3. 回滚事务

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 事务的传播行为

  1. PROPAGATION_REQUIRED:支持当前事务,如果不存在,就新建一个(<font color="red">默认</font>)
  2. PROPAGATION_SUPPORTS:支持当前事务,如果不存在,就不使用事务。
  3. PROPAGATION_MANDATORY:支持当前事务,如果不存在,抛出异常。
  4. PROPAGATION_REQUIRES_NEW:如果有事务存在,挂起当前事务,创建一个新的事务
  5. PROPAGATION_NOT_SUPPORTED:以非事务方式运行,㘝有事务存在,挂起当前事务。
  6. PROPAGATION_NEVER:以非事务方式运行,如果有事务存在,抛出异常
  7. PROPAGATION_NESTED:如果当前事务存在,则嵌套事务执行

三、Spring管理事务方式

  • 原理图

3.1 xml配置(aop)

3.1.1 导包

  1. aop
  2. aspect
  3. aop-alliance
  4. aop-weaver

3.1.2 导入新的约束(tx)

  1. beans:最基本
  2. context:读取properties配置
  3. aop:配置aop
  4. 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>`
<?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);
    }
}
Last modification:September 8th, 2019 at 10:16 am