Spring—CRUD—添加事物管理2020.4.25笔记

1.前言

根据前几天学习Spring内容可以只,所有的配置都可以交给Spring进行管理,但是正是由于Spring 的管理我们可能会出现一些事物上面的问题
比如:银行的操作系统,当A给B转账100时,出现了一些问题,导致A的钱给了但是B没有收到
今天就是解决这个问题
Spring导入的依赖
(这个先不看,后面会说到,这个是为了我后面好复习)
在这里插入图片描述
例如转账
当其中操作失败了,那么就会导致转账失败,更严重会导致系统的奔溃
(仔细看下面的图)
因为每一个accountDao.findAccountByName(xxxx)都会获取一个新的连接
在这里插入图片描述
在这里插入图片描述

解决
把一个转账的业务层设置一个connection,当其中有错误时,直接返还

2.业务层service

业务层代码
业务层接口

package com.xiao.service;

import com.xiao.doamin.Account;

import java.util.List;

/**
 * @_PackageName:com.xiao.sercvice
 * @_ClassName:AccountService
 * @_Description:
 * @_Author:笑老二
 * @_data 2020/4/27 22:33
 */
public interface AccountService {
    /**
     * 查询所有
     * @return
     */
    List<Account> findAllAccount();

    /**
     * 查询一个
     * @return
     */
    Account findAccountById(Integer accountId);

    /**
     * 保存
     * @param account
     */
    void saveAccount(Account account);

    /**
     * 更新
     * @param account
     */
    void updateAccount(Account account);

    /**
     * 删除
     * @param acccountId
     */
    void deleteAccount(Integer acccountId);

    /**
     *
     * @param resourceName 转账人名字
     * @param accName 转账人信息
     * @param money 转账钱数
     */
    void transfer(String resourceName,String accName,Double money);
}

业务层实现类

package com.xiao.service.impl;
import com.xiao.dao.AccountDao;
import com.xiao.doamin.Account;
import com.xiao.service.AccountService;
import com.xiao.utils.TransactionManger;


import java.util.List;

/**
 * @_PackageName:com.xiao.sercvice.impl
 * @_ClassName:AccountServiceImpl
 * @_Description:
 * @_Author:笑老二
 * @_data 2020/4/27 22:33
 */
public class AccountServiceImpl implements AccountService {

    private AccountDao accountDao;
    private TransactionManger txManger;

    public void setTxManger(TransactionManger txManger) {
        this.txManger = txManger;
    }

    public void setAccountDao(AccountDao accountDao) {
        this.accountDao = accountDao;
    }


    public List<Account> findAllAccount() {
        try {
            //1.开启事物
            txManger.beginTransaction();
            //2.执行操作
            List<Account> accounts = accountDao.findAllAccount();
            //3.提交事务
            txManger.commit();
            //4.返回结果
            return accounts;
        }catch (Exception e){
            //5.回滚操作
            txManger.rollback();
            throw new RuntimeException(e);
        }finally {
            //6.释放连接
            txManger.release();
        }
    }


    public Account findAccountById(Integer accountId) {
        try {
            //1.开启事物
            txManger.beginTransaction();
            //2.执行操作
            Account account = accountDao.findAccountById(accountId);
            //3.提交事务
            txManger.commit();
            //4.返回结果
            return account;
        }catch (Exception e){
            //5.回滚操作
            txManger.rollback();
            throw new RuntimeException(e);
        }finally {
            //6.释放连接
            txManger.release();
        }
    }


    public void saveAccount(Account account) {
        try {
            //1.开启事物
            txManger.beginTransaction();
            //2.执行操作
            accountDao.saveAccount(account);
            //3.提交事务
            txManger.commit();
            //4.返回结果
        }catch (Exception e){
            //5.回滚操作
            txManger.rollback();
            throw new RuntimeException(e);
        }finally {
            //6.释放连接
            txManger.release();
        }
    }


    public void updateAccount(Account account) {
        try {
            //1.开启事物
            txManger.beginTransaction();
            //2.执行操作
            accountDao.updateAccount(account);
            //3.提交事务
            txManger.commit();
            //4.返回结果
        }catch (Exception e){
            //5.回滚操作
            txManger.rollback();
            throw new RuntimeException(e);
        }finally {
            //6.释放连接
            txManger.release();
        }
    }

    public void deleteAccount(Integer accountId) {
        try {
            //1.开启事物
            txManger.beginTransaction();
            //2.执行操作
            accountDao.deleteAccount(accountId);
            //3.提交事务
            txManger.commit();
            //4.返回结果
        }catch (Exception e){
            //5.回滚操作
            txManger.rollback();
            throw new RuntimeException(e);
        }finally {
            //6.释放连接
            txManger.release();
        }
    }

    public void transfer(String resourceName, String accName, Double money) {
        try {
            //1.开启事物
            txManger.beginTransaction();
            //2.执行操作
            Account resourceA = accountDao.findAccountByName(resourceName);
            Account accA = accountDao.findAccountByName(accName);
            resourceA.setMoney(resourceA.getMoney()-100d);
            accA.setMoney(accA.getMoney()+100d);
            accountDao.updateAccount(resourceA);
            accountDao.updateAccount(accA);
            //3.提交事务
            txManger.commit();
            //4.返回结果
        }catch (Exception e){
            //5.回滚操作
            txManger.rollback();
            throw new RuntimeException(e);
        }finally {
            //6.释放连接
            txManger.release();
        }

    }
}

3.持久层dao

持久层接口

package com.xiao.dao;

import com.xiao.doamin.Account;

import java.util.List;


/**
 * 账户的持久层接口
 */
public interface AccountDao {

    /**
     * 查询所有
     * @return
     */
    List<Account> findAllAccount();

    /**
     * 查询一个
     * @return
     */
    Account findAccountById(Integer accountId);

    /**
     * 保存
     * @param account
     */
    void saveAccount(Account account);

    /**
     * 更新
     * @param account
     */
    void updateAccount(Account account);

    /**
     * 删除
     * @param acccountId
     */
    void deleteAccount(Integer acccountId);

    /**
     * 根据名称查询账户
     * @param accountName
     * @return  如果有唯一的一个结果就返回,如果没有结果就返回null
     *          如果结果集超过一个就抛异常
     */
    Account findAccountByName(String accountName);


}


持久层实现类

package com.xiao.dao.impl;

import com.xiao.dao.AccountDao;
import com.xiao.doamin.Account;
import com.xiao.utils.ConnectionUtils;
import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.handlers.BeanHandler;
import org.apache.commons.dbutils.handlers.BeanListHandler;

import java.util.List;

/**
 * @_PackageName:com.xiao.dao.impl
 * @_ClassName:AccountDaoImpl
 * @_Description:
 * @_Author:笑老二
 * @_data 2020/4/27 22:34
 */
public class AccountDaoImpl implements AccountDao {

    private QueryRunner runner;
    private ConnectionUtils connectionUtils;


    //不希望连接从数据源中拿,那么直接可以控制它
    public void setConnectionUtils(ConnectionUtils connectionUtils) {
        this.connectionUtils = connectionUtils;
    }

    public void setRunner(QueryRunner runner) {
        this.runner = runner;
    }

    public List<Account> findAllAccount() {
        try{
            return runner.query(connectionUtils.getThreadConnection(),"select * from account",new BeanListHandler<Account>(Account.class));
        }catch (Exception e) {
            throw new RuntimeException(e);
        }
    }


    public Account findAccountById(Integer accountId) {
        try{
            return runner.query(connectionUtils.getThreadConnection(),"select * from account where id = ? ",new BeanHandler<Account>(Account.class),accountId);
        }catch (Exception e) {
            throw new RuntimeException(e);
        }
    }


    public void saveAccount(Account account) {
        try{
            runner.update(connectionUtils.getThreadConnection(),"insert into account(name,money)values(?,?)",account.getName(),account.getMoney());
        }catch (Exception e) {
            throw new RuntimeException(e);
        }
    }


    public void updateAccount(Account account) {
        try{
            runner.update(connectionUtils.getThreadConnection(),"update account set name=?,money=? where id=?",account.getName(),account.getMoney(),account.getId());
        }catch (Exception e) {
            throw new RuntimeException(e);
        }
    }


    public void deleteAccount(Integer accountId) {
        try{
            runner.update(connectionUtils.getThreadConnection(),"delete from account where id=?",accountId);
        }catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    public Account findAccountByName(String accountName) {
        try{
          return runner.query(connectionUtils.getThreadConnection(),"select * from account where name = ?",new BeanHandler<Account>(Account.class),accountName);
        }catch (Exception e){
            throw new RuntimeException(e);
        }
    }
}

4.获取连接ConnectionUtils

package com.xiao.utils;

import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.SQLException;

/**
 * @_PackageName:com.xiao.utils
 * @_ClassName:ConnectionUtils
 * @_Description:
 * @_Author:笑老二
 * @_data 2020/4/28 19:36
 */
public class ConnectionUtils {
    private ThreadLocal<Connection> tl = new ThreadLocal<Connection>();

    public DataSource dataSource;

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

    /**
     *
     * @return 获取当前线程上的连接
     */
    public Connection getThreadConnection(){
        try {
            //1.从ThreadLocal上面获取
            Connection conn = tl.get();
            //2.判断当前线程上是否有连接
            if (conn == null){
                //3.从数据源中获取一个连接,并且存入ThreadLocal中
                conn = dataSource.getConnection();
                //4.把connection传入ThreadLocal中
                tl.set(conn);
            }
            //5.返回当前线程上的连接
            return conn;
        } catch (SQLException e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 返回线程
     */
    public void removeConnection(){
        tl.remove();
    }
}

5.事物管理TransactionManger

package com.xiao.utils;

import java.sql.SQLException;

/**
 * @_PackageName:com.xiao.utils
 * @_ClassName:TransactionManger
 * @_Description:事物管理的相关类
 * @_Author:笑老二
 * @_data 2020/4/28 19:43
 */
public class TransactionManger {
    private ConnectionUtils connectionUtils;

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

    /**
     * 开启事物
     */
    public void beginTransaction(){
        try {
            connectionUtils.getThreadConnection().setAutoCommit(false);
        } catch (SQLException e) {
            throw new RuntimeException(e);
        }
    }
    /**
     * 提交事物
     */
    public void commit(){
        try {
            connectionUtils.getThreadConnection().commit();
        } catch (SQLException e) {
            throw new RuntimeException(e);
        }
    }
    /**
     * 回滚事物
     */
    public void rollback(){
        try {
            connectionUtils.getThreadConnection().rollback();
        } catch (SQLException e) {
            throw new RuntimeException(e);
        }
    }
    /**
     * 关闭事物
     */
    public void release(){
        try {
            connectionUtils.getThreadConnection().close();
            connectionUtils.removeConnection();
        } catch (SQLException e) {
            throw new RuntimeException(e);
        }
    }
}

6.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">

    <!-- 配置Service -->
    <bean id="accountService" class="com.xiao.service.impl.AccountServiceImpl">
        <property name="accountDao" ref="accountDao"/>
        <!--注入事物管理器-->
        <property name="txManger" ref="transactionManger"/>
    </bean>

    <!--配置Dao-->
    <bean id="accountDao" class="com.xiao.dao.impl.AccountDaoImpl">
        <property name="runner" ref="runner"/>
        <!--注入connectionUtils-->
        <property name="connectionUtils" ref="connectionUtils"/>
    </bean>

    <!--jdbcTemplate-->
    <bean id="runner" class="org.apache.commons.dbutils.QueryRunner" scope="prototype"/>

    <!--配置dataSource-->
    <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
        <property name="driverClassName" value="com.mysql.jdbc.Driver"/>
        <property name="url" value="jdbc:mysql://localhost:3306/eesy_spring_account"/>
        <property name="username" value="root"/>
        <property name="password" value="1234"/>
    </bean>

    <!--配合connectionUtils-->
    <bean id="connectionUtils" class="com.xiao.utils.ConnectionUtils">
        <!--注入数据源-->
        <property name="dataSource" ref="dataSource"/>
    </bean>

    <!--配置事物管理器-->
    <bean id="transactionManger" class="com.xiao.utils.TransactionManger">
        <property name="connectionUtils" ref="connectionUtils"/>
    </bean>
</beans>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值