转账案例

四.转账案例:
描述:一个人的账户减少,另一个人的账户增加相同金额.
步骤:
     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      }

原文地址:https://www.cnblogs.com/huguangqin/p/7137599.html