zoukankan      html  css  js  c++  java
  • 转账案例

    四.转账案例:
    描述:一个人的账户减少,另一个人的账户增加相同金额.
    步骤:
         1.Eclipse创建工程transfer,并添加jar包:mysql-connector;c3p0(c3p0-config.xml放在src文件夹下);commens-dbutils;
         2.创建5个包:web/service/DAO/Account类/utils
         3.创建数据库bank,添加数据表account(id,name,money);(用于与Account类相关联)
         4.web层是供客户使用的,只用于输入信息,及展示运行结果(转账成功或失败)
         5.serive层用于转账操作,并返回给web层转账成功或失败的信息;
         6.DAO层用于操作数据库,即查询是否有客户输入的相关信息,并将查询结果封装成类(javabean),返回给service层;
    代码演示:
    web层:
        

      1 package huguangqin.cnblogs.web;
      2      import huguangqin.cnblogs.service.Service;
      3      import java.util.Scanner;
      4      //该层展示给客户,用于收集信息,展示数据及结果
      5     public class MyAPP {
      6          public static void main(String[] args) {
      7              // 提示用户输入
      8             Scanner sc = new Scanner(System.in);
      9              System.out.print("请输入付款人姓名:");
     10              String payName = sc.next();
     11              System.out.print("请输入收款人姓名:");
     12              String receiptName = sc.next();
     13              System.out.print("请输入金额:");
     14              double money = sc.nextDouble();
     15 
     16              // 面向service层,返回转账结果
     17             Service ser = new Service();
     18             String message = ser.transfer(payName, receiptName, money);
     19              System.out.println(message);
     20          }
     21 
     22     }

    service层:
        

      1 package huguangqin.cnblogs.service;
      2      import huguangqin.cnblogs.DAO.DAO;
      3      import huguangqin.cnblogs.domain.Account;
      4      import huguangqin.cnblogs.utils.ConnectionManager;
      5      public class Service {
      6          public String transfer(String payName, String receiptName, double money) {
      7              // 开启事务
      8             ConnectionManager.startTransaction();
      9 
     10              // 根据传入的收/付款人姓名在数据库中查找是否存在--以后所有的步骤都是面向Account操作
     11             DAO d = new DAO();
     12              Account payAccount = d.queryAccount(payName);
     13              if (payAccount == null) {
     14                  ConnectionManager.rollback();
     15                  return "付款账户不存在";
     16              }
     17 
     18              Account receiptAccount = d.queryAccount(receiptName);
     19              if (receiptAccount == null) {
     20                  ConnectionManager.rollback();
     21                  return "收款账户不存在";
     22              }
     23 
     24              // 根据传入的金额,查询余额是否足够
     25             if (payAccount.getMoney() >= money) {
     26                  payAccount.setMoney(payAccount.getMoney() - money);
     27              } else {
     28                  ConnectionManager.rollback();
     29                  return "余额不足";
     30              }
     31              receiptAccount.setMoney(receiptAccount.getMoney() + money);
     32 
     33              int i = d.update(payAccount);
     34              int j = d.update(receiptAccount);
     35 
     36              // 根据操作的结果,返回操作是否成功
     37             if (i == 1 && j == 1) {
     38                  ConnectionManager.commit();
     39                  return "转账成功,金额:" + money + "";
     40              } else {
     41                  ConnectionManager.rollback();
     42                  return "服务器升级...,转账失败";
     43              }
     44          }
     45      }

    DAO(Data Access Object)层:
        

      1 package huguangqin.cnblogs.DAO;
      2      import huguangqin.cnblogs.domain.Account;
      3      import huguangqin.cnblogs.utils.ConnectionManager;
      4      import java.sql.Connection;
      5      import java.sql.SQLException;
      6      import org.apache.commons.dbutils.QueryRunner;
      7      import org.apache.commons.dbutils.handlers.BeanHandler;
      8      //该层用于操作数据库-创建-查询-更新
      9     public class DAO {
     10          // 能否将QueryRunner/Connection作为成员变量?
     11          private static QueryRunner qr = new QueryRunner();
     12          private static Connection conn = ConnectionManager.getConnectionThreadLocal();
     13 
     14          /*
     15           * 查询数据库 返回值:Account 参数:String name 方法名:queryAccount
     16           */
     17          public Account queryAccount(String name) {
     18              // 获取本地线程连接对象
     19             String querySql = "SELECT * FROM account WHERE name = ?";
     20              BeanHandler<Account> bh = new BeanHandler<>(Account.class);
     21              Account queryAccount = null;
     22              try {
     23                  queryAccount = qr.query(conn, querySql, bh, name);
     24              } catch (SQLException e) {
     25                  e.printStackTrace();
     26              }
     27              return queryAccount;
     28          }
     29 
     30          /*
     31           * 更新数据库 方法名:update 返回值:int 参数:money-转账金额
     32          */
     33 
     34          public int update(Account a) {
     35              String updateSql = "UPDATE account SET money = ? WHERE id = ?";
     36              int i = 0;
     37              try {
     38                  i = qr.update(conn, updateSql, a.getMoney(), a.getId());
     39              } catch (SQLException e) {
     40                  e.printStackTrace();
     41              }
     42              return i;
     43          }
     44      }

    domain层:
        

      1 package huguangqin.cnblogs.domain;
      2      //javabean
      3      public class Account {
      4          private int id;// 账户ID
      5          private String name;// 账户名
      6         private double money;// 余额
      7 
      8          public Account() {
      9              super();
     10          }
     11 
     12          public Account(int id, String name, double money) {
     13              super();
     14              this.id = id;
     15              this.name = name;
     16              this.money = money;
     17          }
     18 
     19          public int getId() {
     20              return id;
     21          }
     22 
     23          public void setId(int id) {
     24              this.id = id;
     25          }
     26 
     27          public String getName() {
     28              return name;
     29          }
     30 
     31          public void setName(String name) {
     32              this.name = name;
     33          }
     34 
     35          public double getMoney() {
     36              return money;
     37          }
     38 
     39          public void setMoney(double money) {
     40              this.money = money;
     41          }
     42 
     43          @Override
     44          public String toString() {
     45             return "Account [id=" + id + ", name=" + name + ", money=" + money
     46                      + "]";
     47          }
     48 
     49      }

    utils包://ConnectionManager工具
        

      1 package huguangqin.cnblogs.utils;
      2      import java.sql.Connection;
      3      import java.sql.SQLException;
      4      //该工具用于事务管理
      5     public class ConnectionManager {
      6          // 面向Connection进行事务管理,因此首先获取Connection,并存放于ThreadLocal,规避线程安全问题
      7         private static ThreadLocal<Connection> threadLocal = new ThreadLocal<>();
      8 
      9          // 获取本线程的Connection连接,因为后面的事务管理全部是面向Connection对象的
     10         public static Connection getConnectionThreadLocal() {
     11              Connection conn = threadLocal.get();// 注意要从当前线程获取,不要利用MyC3P0创建!!!
     12              if (conn == null) {
     13                  // 如果连接为空,则通过MyC3P0工具获取并存放线程一个连接
     14                 conn = MyC3P0.getConnection();
     15                  threadLocal.set(conn);
     16              }
     17              return conn;
     18          }
     19 
     20          // 面向获取到的本地线程的连接对象,开启事务
     21         public static void startTransaction() {
     22              try {
     23                  getConnectionThreadLocal().setAutoCommit(false);
     24              } catch (SQLException e) {
     25                  e.printStackTrace();
     26                  throw new RuntimeException("事务开启失败");
     27              }
     28          }
     29 
     30          // 面向本地线程的连接对象,提交事务
     31         public static void commit() {
     32              try {
     33                  getConnectionThreadLocal().commit();
     34              } catch (SQLException e) {
     35                  e.printStackTrace();
     36                  throw new RuntimeException("提交失败!");
     37              }
     38          }
     39 
     40          // 面向本地线程的连接对象,回滚事务
     41         public static void rollback() {
     42              try {
     43                  getConnectionThreadLocal().rollback();
     44              } catch (SQLException e) {
     45                  e.printStackTrace();
     46                  throw new RuntimeException("回滚失败!");
     47              }
     48         }
     49      }

    //MyC3P0工具类
       

      1  package huguangqin.cnblogs.utils;
      2      import java.sql.Connection;
      3      import java.sql.SQLException;
      4      import javax.sql.DataSource;
      5      import com.mchange.v2.c3p0.ComboPooledDataSource;
      6 
      7      //MyC3P0工具用于建立资源池,并从池中获取Connection
      8      public class MyC3P0 {
      9          // 创建连接池
     10         private static DataSource ds = new ComboPooledDataSource();
     11 
     12          // 创建方法获取资源池中Connection对象
     13         public static Connection getConnection() {
     14              Connection conn = null;
     15              try {
     16                  conn = ds.getConnection();
     17              } catch (SQLException e) {
     18                  e.printStackTrace();
     19              }
     20              return conn;
     21          }
     22 
     23          // 返回连接池
     24         public static DataSource getDataSource() {
     25              return ds;
     26          }
     27 
     28      }

  • 相关阅读:
    将Python脚本变为命令行--click模块使用
    MongoDB大批量读写数据优化记录
    [转]MongoDB更新操作replaceOne()实例讲解
    pip 18.1: pipenv graph results in ImportError: cannot import name 'get_installed_distributions'
    mitmdump 屏蔽443错误
    python3 操作appium
    appium-Could not obtain screenshot: [object Object]
    scrapy主动触发关闭爬虫
    匿名函数
    装饰器1、无参数的装饰器 2、有参数的装饰器 3、装饰器本身带参数的以及如果函数带return结果的情况
  • 原文地址:https://www.cnblogs.com/huguangqin/p/7137599.html
Copyright © 2011-2022 走看看