【ssm入门#7-Spring5】事务控制+动态代理增强事务控制方式+Spring AOP实现方法增强(切片表达式、通知类型)+纯注解配置AOP

本文基于下述教程编写:【B站】ssm教程事务控制事务要满足四大特性:原子性、一致性、隔离性、持久性。AB之间的转账操作一定要满足数据库金额总额不变的条件。因此,事务控制就很有必要。否则一整个转账操作只是多个Dao操作,遇到异常基本导致后续无法执行,并且数据库已经遭到修改,这时候整个操作的事务回滚特别重要。还有想要控制事务,只能够向当前线程提供一个连接Connection,我们应该准备一个事务控制类、一个获取连接工具类分离两个业务逻辑。事务控制类TransactionManager:/** *
摘要由CSDN通过智能技术生成

本文基于下述教程编写:【B站】ssm教程

事务控制

事务要满足四大特性:原子性一致性隔离性持久性
AB之间的转账操作一定要满足数据库金额总额不变的条件。
因此,事务控制就很有必要。否则一整个转账操作只是多个Dao操作,遇到异常基本导致后续无法执行,并且数据库已经遭到修改,这时候整个操作的事务回滚特别重要。还有想要控制事务,只能够向当前线程提供一个连接Connection,我们应该准备一个事务控制类、一个获取连接工具类分离两个业务逻辑。

事务控制类TransactionManager

/**
 * 事务管理工具类,开启事务、提交事务、回滚事务、释放连接
 */
public class TransactionManager {
   

    private ConnectionUtils connectionUtils;

    public void setConnectionUtils(ConnectionUtils connectionUtils) {
   
        this.connectionUtils = connectionUtils;
    }

    /**
     * 开启事务
     */
    public void beginTransaction(){
   
        try {
   
            connectionUtils.getThreadConnection().setAutoCommit(false);
        } catch (SQLException throwables) {
   
            throwables.printStackTrace();
        }
    }
    /**
     * 提交事务
     */
    public void commit(){
   
        try {
   
            connectionUtils.getThreadConnection().commit();
        } catch (SQLException throwables) {
   
            throwables.printStackTrace();
        }
    }
    /**
     * 回滚事务
     */
    public void rollback(){
   
        try {
   
            connectionUtils.getThreadConnection().rollback();
        } catch (SQLException throwables) {
   
            throwables.printStackTrace();
        }
    }
    /**
     * 释放连接
     */
    public void release(){
   
        try {
   
            //还回连接池中
            connectionUtils.getThreadConnection().close();
            /**
             * 服务器提供一个线程,该线程拥有一个Connection,当线程关闭Connection时
             * Connection就不能用了,线程结束会还回服务器线程池,但是此时还回去的线程
             * 还拥有一个已经关闭了的Connection,再次调用该线程获取连接时,一定存在Connection
             * 但已经关闭还回连接池不能再使用,所以需要线程和连接解绑
             */
            connectionUtils.remove();
        } catch (SQLException throwables) {
   
            throwables.printStackTrace();
        }
    }
}

值得注意的是,释放Connection的时候,不仅要归还连接池还是和线程解绑,不然释放后再次获取已经存在绑定的Connection就不能用了。

连接工具类ConnectionUtils

/**
 * 连接工具类,它用于从数据源获取一个连接,并且实现和线程绑定
 */
public class ConnectionUtils {
   
    private ThreadLocal<Connection> threadLocal = new ThreadLocal<>();

    private DataSource dataSource;

    public void setDataSource(DataSource dataSource) {
   
        this.dataSource = dataSource;
    }

    /**
     * 获取当前线程上的连接
     */
    public Connection getThreadConnection() {
   
        try {
   
            //1.先从ThreadLocal上获取
            Connection conn = threadLocal.get();
            //2.判断线程上有无连接
            if (conn == null) {
   
                //3.从数据源中获取一个连接,并且存入ThreadLocal中
                conn = dataSource.getConnection();
                threadLocal.set(conn);
            }
            return conn;
        } catch (Exception e) {
   
            throw new RuntimeException(e);
        }
    }

    public void remove(){
   
        threadLocal.remove();
    }
}

ThreadLocal中填充的变量属于当前线程,该变量对其他线程而言是隔离的。ThreadLocal为变量在每个线程中都创建了一个副本,那么每个线程可以访问自己内部的副本变量。用来存储控制事务操作的Connection最恰当不过。

Spring容器配置bean.xml:

<?xml version="1.0" encoding="utf-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       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">
    <!--服务层AccountService-->
    <bean id="accountService" class="com.spring_aop.service.impl.AccountServiceImpl">
        <property  name="accountDao" ref="accountDao"></property >
        <property name="transactionManager" ref="transactionManager"></property>
    </bean>

    <!--持久层AccountDao-->
    <bean id="accountDao" class="com.spring_aop.dao.impl.AccountDaoImpl">
        <property name="runner" ref="runner"></property >
        <property name="connectionUtils" ref="connectionUtils"></property >
    </bean>

    <!--持久层AccountDao成员属性QueryRunner-->
    <bean id="runner" class="org.apache.commons.dbutils.QueryRunner" scope="prototype">
        <!--取消向QueryRunner注入连接-->
        <!--<constructor-arg name="ds" ref="dataSource"> 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值