spring学习笔记(6):银行转账案例、动态代理

一、Spring实现银行转账案例

1.代码实现

1.1 持久层

  • 提供根据账户名查询账户的方法
    public Account findAccountByName(String accountName) {
   
        try{
   
           List<Account> accounts = runner.query("select * from account where name = ? ",new BeanListHandler<Account>(Account.class),accountName);
           //根据查询结果 做逻辑判断
            //1.没有该账户
            if (accounts == null || accounts.size() == 0){
   
                return null;
            }
            if (accounts.size() > 1){
   
                throw new RuntimeException("结果集不唯一,数据有问题");
            }
            return accounts.get(0);
        }catch (Exception e) {
   
            throw new RuntimeException(e);
        }
    }

1.2 业务层

  • 提供转账方法
 public void transfer(String sourceName, String targetName, Float money) {
   
        //1.根据sourceName 获取转出账户
        Account source = accountDao.findAccountByName(sourceName);
        //2.根据targetName 获取转入账户
        Account target = accountDao.findAccountByName(targetName);
        //3.转出账户增加金额 转入账户减少金额
        source.setMoney(source.getMoney() - money);
        target.setMoney(target.getMoney() + money);
        //4. 数据库更新账户余额
        accountDao.updateAccount(source);
        accountDao.updateAccount(target);

    }

1.3测试类

  • 测试转账过程
   @Test
    public void testTransfer(){
   
        //1.获取IOC容器
        ApplicationContext ac = new ClassPathXmlApplicationContext("bean.xml");
        //2.获取service对象
        IAccountService as = ac.getBean("accountService",IAccountService.class);
        //3.调用转账方法
        as.transfer("aaa", "bbb", 100f);
    }
1.3.1结果

在这里插入图片描述- 可以实现转账,但是存在问题,下面分析

2.缺乏事务控制带来的问题

  • 上述转账过程看似正确,但是存在巨大的问题,因为没有事务控制,所以如果转账过程发生异常,则会出现问题

2.1问题现象

  • 人为制造异常
    在这里插入图片描述

2.2原因分析

在这里插入图片描述

二、添加事务控制

添加事务控制尝试解决上述的问题

1创建获取连接工具类

  • 连接工具类,用于从数据源中获取一个连接,然后和线程绑定
  • 要注意线程回收时和连接的解绑操作
public class ConnectionUtils {
   
    private ThreadLocal<Connection> tl = new ThreadLocal<Connection>();
    //这个对象只能由Spring来创建
    private DataSource dataSource;
    //所以提供set方法 来完成后面的数据注入
    public void setDataSource(DataSource dataSource) {
   
        this.dataSource = dataSource;
    }
    /**
     * 获取当前线程上的连接
     * @return
     */
    public Connection getThreadConnection(){
   
        //1.先获取连接
        Connection conn = tl.get();
        try {
   
            //2.判断当前线程上是否有连接
            if (conn == null){
   
                //如果没有则创建 并存入tl中
                conn = dataSource.getConnection();
                tl.set(conn);
            }
            //返回当前线程上的连接
            return conn
  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 8
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值