完成转账的案例v4

需求

  • 当单击提交按钮,付款方向收款方按照输入的金额转账。 使用事务进行控制

  • 分析

    1.ThreadLocal

    在“事务传递参数版”中,我们必须修改方法的参数个数,传递连接对象,才可以完成整个事务操作。如果不传递参数,是否可以完成?在JDK中给我们提供了一个工具类:ThreadLocal,此类可以在一个线程中共享数据。

    java.lang.ThreadLocal,该类提供了线程局部 (thread-local) 变量,用于在当前线程中共享数据。ThreadLocal工具类底层就是一个Map,key存放的当前线程,value存放需要共享的数据

  • //模拟ThreadLocal类 
    public class ThreadLocal{
        private Map<Thread,Object> map = new HashMap<Thread,Object>();
        
        public void set(Connection conn){
            map.put(Thread.currentThread(),conn); //以当前线程对象作为key
        }
            
        public Object get(){
            return map.get(Thread.currentThread()); //只有当前线程才能取出value数据
        }
    }
    ThreadLocal:实现在当前线程下共享数据【范围小很多】  
    类似于ServletContext在当前应用下共享数据【范围大一些】
    结论:向ThreadLocal对象中添加的数据只能在当前线程下使用。

  • 思路

  • 代码

    package com.itheima.utils;

    import java.sql.Connection;

    public class ConnectionManager {

        private static ThreadLocal<Connection> t = new ThreadLocal<>();

        public static Connection getConnection() throws Exception {
            //1.从ThreadLocal中获取connection对象
            Connection connection = t.get();
            //2.第一次获取的时候ThreadLocal中还没有存储connection对象  因此获取之后,将connection存入到ThreadLocal中,这样后面同一个线程就可以获取到了
            if(connection==null){
                connection = C3P0Utils.getConnection();
                t.set(connection);
            }
            return  connection;
        }

    }

  • UserService

  • package com.itheima.service;

    import com.itheima.dao.TransferDao;
    import com.itheima.utils.C3P0Utils;
    import com.itheima.utils.ConnectionManager;

    import java.sql.Connection;
    import java.sql.SQLException;

    public class TransferService {

        /**
         * 转账业务
         * @param from  付款方
         * @param to    收款方
         * @param money 转账金额
         * @return 转账是否成功  true|false
        */
        public boolean transfer(String from, String to, double money) throws Exception {

            /********1.手动开启事务*******/
            Connection connection = ConnectionManager.getConnection();
            connection.setAutoCommit(false);

            try {
                //1.处理业务【判断付款方 收款方是否存在 转账金额是否合理  假设一切正常】
                //2.调用dao
                TransferDao transferDao = new TransferDao();
                //2.1:付款方钱减少
                int rows1 = transferDao.reduceMoney(from,money);

                //人为制作异常 用于测试
                //int i = 1/0;

                //2.2:收款方钱增加
                int rows2 = transferDao.addMoney(to,money);
                //3.根据dao处理结果判断转账是否成功 并返回
                if(rows1>0 && rows2>0){
                    //转账成功 提交事务
                    connection.commit();
                    return true;
                }else{
                    //转账失败 回滚事务
                    connection.rollback();
                    return false;
                }
            } catch (Exception e) {
                e.printStackTrace();
                //发生异常 回滚事务
                connection.rollback();
                return false;
            }

        }
    }

  • UserDao

  • package com.itheima.dao;

    import com.itheima.utils.C3P0Utils;
    import com.itheima.utils.ConnectionManager;
    import org.apache.commons.dbutils.QueryRunner;

    import java.sql.Connection;
    import java.sql.SQLException;

    public class TransferDao {

        /**
         * 付款方钱减少
         * @param from
         * @param money
         * @return
         */
        public int reduceMoney(String from, double money) throws Exception {
            //1.操作数据库
            //注意:多个操作使用同一个connection时,才能进行事务控制  所以此时创建QueryRunner对象时使用无参构造方法
            QueryRunner queryRunner = new QueryRunner();
            String sql = "update account set money = money-? where name=?";
            return queryRunner.update(ConnectionManager.getConnection(),sql,money,from);
        }

        /**
         * 收款方钱增加
         * @param to
         * @param money
         * @return
         */
        public int addMoney(String to, double money) throws Exception {
            //1.操作数据库
            QueryRunner queryRunner = new QueryRunner();
            String sql = "update account set money = money+? where name=?";
            return queryRunner.update(ConnectionManager.getConnection(),sql,money,to);
        }
    }

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值