使用JDBC完成一个简单的银行ATM系统
项目整体结构图如下:

实现步骤:
1.在src下编写druid.properties属性文档
#druid.properties文件的配置
driverClassName=com.mysql.cj.jdbc.Driver
url=jdbc:mysql://localhost:3306/test?serverTimezone=Asia/Shanghai&characterEncoding=utf8&useUnicode=true&useSSL=true
username=root
password=root
#初始化连接数量
initialSize=50
#最大连接数
maxActive=200
#最新空闲数量
minIdle=5
#最大超时时间
maxWait=3000
2.定义DruidDbUtil工具类
package com.oracle.jdbc.demo.util;
import com.alibaba.druid.pool.DruidDataSource;
import java.io.InputStream;
import java.sql.*;
import java.util.List;
import java.util.Properties;
public class DruidDBUtil {
//声明druid连接池对象
private static DruidDataSource dataSource = null;
//访问数据库的小帮手
private static String url = null;
private static String username = null;
private static String password = null;
/**
* 初始连接数
**/
private static int initialSize;
/**
* 最大活动连接数
**/
private static int maxActive;
/**
* 最小闲置连接数
**/
private static int minIdle;
/**
* 连接耗尽时最大等待获取连接时间
**/
private static long maxWait;
//保证线程安全的数据库访问,一个线程只绑定一个链接对象,多次访问时同一个连接对象
private static ThreadLocal<Connection> tl = new ThreadLocal<Connection>();
private DruidDBUtil() {
}
static {
initPool();
}
//初始化数据库连接池
private static void initPool() {
try {
Properties pro = new Properties();
InputStream in = DruidDBUtil.class.getClassLoader().getResourceAsStream("druid.properties");
pro.load(in); //读取属性文档配置信息
String driverClassName = pro.getProperty("driverClassName");
Class.forName(driverClassName);
url = pro.getProperty("url");
username = pro.getProperty("username");
password = pro.getProperty("password");
initialSize = Integer.parseInt(pro.getProperty("initialSize"));
maxActive = Integer.parseInt(pro.getProperty("maxActive"));
maxWait = Integer.parseInt(pro.getProperty("maxWait"));
minIdle = Integer.parseInt(pro.getProperty("minIdle"));
//创建druid数据源
dataSource = new DruidDataSource();
dataSource.setUrl(url);
dataSource.setUsername(username);
dataSource.setPassword(password);
//设置连接池中初始连接数
dataSource.setInitialSize(initialSize);
//设置最大连接数
dataSource.setMaxActive(maxActive);
//设置最小的闲置链接数
dataSource.setMinIdle(minIdle);
//设置最大的等待时间(等待获取链接的时间)
dataSource.setMaxWait(maxWait);
} catch (Exception ex) {
ex.printStackTrace();
}
}
//由于使用了数据库连接池,我们不采用单例模式
public static Connection getConnection() throws Exception {
// 先从当前线程上获得链接
Connection conn = tl.get();
try {
if (conn == null || conn.isClosed()) {
//从连接池中获取连接对象
conn = dataSource.getConnection();
// 把连接绑定到当前线程上
tl.set(conn);
}
} catch (SQLException e) {
e.printStackTrace();
}
return conn;
}
//关闭所有数据库访问对象
public static void closeAll() {
try {
if (DruidDBUtil.getConnection() != null && !DruidDBUtil.getConnection().isClosed())
DruidDBUtil.getConnection().close();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
// 所有的增删改的方法
public static int executeUpdate(String sql, List list) throws Exception {
//添加第二个参数的意义是为了获得新增记录的主键。
PreparedStatement pstm = getConnection().prepareStatement(sql, Statement.RETURN_GENERATED_KEYS);
if (list != null) {
for (int i = 0; i < list.size(); i++) {
pstm.setObject(i + 1, list.get(i));
}
}
return pstm.executeUpdate();
}
//执行批处理
public static int[] executeBatch(String sql,List<List> list) throws Exception{
//添加第二个参数的意义是为了获得新增记录的主键。
PreparedStatement pstm = getConnection().prepareStatement(sql, Statement.RETURN_GENERATED_KEYS);
if (list != null) {
for (int i = 0; i < list.size(); i++) {
for(int j=0; j< list.get(i).size();j++){
pstm.setObject(j + 1, list.get(i).get(j));
}
pstm.addBatch();
}
}
return pstm.executeBatch();
}
//执行批处理返回主键的集合
public static long[] executeBatchWithReturnKeys(String sql,List<List> list) throws Exception{
//添加第二个参数的意义是为了获得新增记录的主键。
PreparedStatement pstm = getConnection().prepareStatement(sql, Statement.RETURN_GENERATED_KEYS);
long[] keys = null;
if (list != null) {
keys = new long[list.size()];
for (int i = 0; i < list.size(); i++) {
keys[i] = executeUpdateWithReturnKey(sql,list.get(i));
}
}
return keys;
}
//执行更新语句并且返回新增记录的主键值,主键值为long类型
public static long executeUpdateWithReturnKey(String sql, List list) throws Exception {
//添加第二个参数的意义是为了获得新增记录的主键。
PreparedStatement pstm = getConnection().prepareStatement(sql, Statement.RETURN_GENERATED_KEYS);
if (list != null) {
for (int i = 0; i < list.size(); i++) {
pstm.setObject(i + 1, list.get(i));
}
}
pstm.executeUpdate();
ResultSet rs = pstm.getGeneratedKeys();
long key = -1;
//注意:这里必须把游标指向第一条记录。
if(rs.next()){
key = rs.getLong(1);
}
return key;
}
//所有的查询的方法
public static ResultSet executeQuery(String sql, List list) throws Exception{
PreparedStatement pstm = getConnection().prepareStatement(sql);
if (list != null) {
for (int i = 0; i < list.size(); i++) {
pstm.setObject(i + 1, list.get(i));
}
}
return pstm.executeQuery();
}
//开启事务
public static void startTransaction() {
Connection conn = null;
try {
conn = getConnection();
conn.setAutoCommit(false);
} catch (Exception e) {
e.printStackTrace();
}
}
//提交事务
public static void commit() {
Connection conn = null;
try {
conn = getConnection();
conn.commit();
} catch (Exception e) {
e.printStackTrace();
}
}
//回滚
public static void rollback() {
Connection conn = null;
try {
conn = getConnection();
conn.rollback();
} catch (Exception e) {
e.printStackTrace();
}
}
//释放资源
public static void release() {
Connection conn = null;
try {
conn = getConnection();
conn.close();
tl.remove();// 与线程池有关,解除关系
} catch (Exception e) {
e.printStackTrace();
}
}
//关闭事务
public static void endTransaction() {
Connection conn = null;
try {
conn = getConnection();
conn.setAutoCommit(true);
} catch (Exception e) {
e.printStackTrace();
}
}
}
3.设计Account类
package com.oracle.jdbc.demo.domain;
public class Account {
private String cid; //银行卡账号
private String name; //户主
private String password; //取款密码
private int balance; //余额
private String modifydate; //最后修改日期
public String getCid() {
return cid;
}
public void setCid(String cid) {
this.cid = cid;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public int getBalance() {
return balance;
}
public void setBalance(int balance) {
this.balance = balance;
}
public String getModifydate() {
return modifydate;
}
public void setModifydate(String modifydate) {
this.modifydate = modifydate;
}
@Override
public String toString() {
return "Account{" +
"cid='" + cid + '\'' +
", name='" + name + '\'' +
", password='" + password + '\'' +
", balance=" + balance +
", modifydate='" + modifydate + '\'' +
'}';
}
}
4.设计AccountService类,该类封装了账户的所有业务逻辑方法。
package com.oracle.jdbc.demo.atm;
import com.oracle.jdbc.demo.domain.Account;
import com.oracle.jdbc.demo.util.DruidDBUtil;
import java.sql.ResultSet;
import java.text.SimpleDateFormat;
import java.util.*;
//封装了银行ATM的常用方法
public class AccountService {
public static Scanner sc = new Scanner(System.in);
private String createAccountCid() {
return UUID.randomUUID().toString().replaceAll("-", "");
}
//开户
public Account createAccount() {
String sql = "insert into account (cid,name,password,balance,modifydate) values (?,?,?,?,?)";
List argsList = new ArrayList();
String name;
String password;
try {
System.out.println("请输入您的姓名:");
name = sc.next();
System.out.println("请设置您的银行卡密码:");
password = sc.next();
Account account = new Account();
account.setCid(createAccountCid());
account.setName(name);
account.setPassword(password);
account.setBalance(0);
account.setModifydate(new SimpleDateFormat("yyyy-MM-dd").format(new Date()));
argsList.add(account.getCid());
argsList.add(account.getName());
argsList.add(account.getPassword());
argsList.add(account.getBalance());
argsList.add(account.getModifydate());
//开启事务
DruidDBUtil.startTransaction();
DruidDBUtil.executeUpdate(sql, argsList);
DruidDBUtil.commit();
DruidDBUtil.endTransaction();
return account;
} catch (Exception ex) {
ex.printStackTrace();
DruidDBUtil.rollback();
DruidDBUtil.commit();
return null;
} finally {
DruidDBUtil.closeAll();
}
}
//存钱
public boolean deposit(Account account, int money) {
String sql = "update account set balance = balance + ? where cid = ?";
List argsList = new ArrayList();
argsList.add(money);
argsList.add(account.getCid());
try {
DruidDBUtil.startTransaction();
DruidDBUtil.executeUpdate(sql, argsList);
DruidDBUtil.commit();
DruidDBUtil.endTransaction();
return true;
} catch (Exception ex) {
ex.printStackTrace();
DruidDBUtil.rollback();
DruidDBUtil.commit();
return false;
} finally {
DruidDBUtil.closeAll();
}
}
//取款
public boolean withdraw(Account account, int money) {
int balance = queryBalanceByCid(account.getCid());
if(balance< money){
System.out.println("余额不足!");
return false;
}
String sql = "update account set balance = balance - ? where cid = ?";
List argsList = new ArrayList();
argsList.add(money);
argsList.add(account.getCid());
try {
DruidDBUtil.startTransaction();
DruidDBUtil.executeUpdate(sql, argsList);
DruidDBUtil.commit();
DruidDBUtil.endTransaction();
return true;
} catch (Exception ex) {
ex.printStackTrace();
DruidDBUtil.rollback();
DruidDBUtil.commit();
return false;
} finally {
DruidDBUtil.closeAll();
}
}
//转账
public boolean transfer(String sourceId, String destId, int number) {
int balance = queryBalanceByCid(sourceId);
if(balance<number){
System.out.println("余额不足!");
return false;
}
String sql = "update account set balance = balance + ? where cid = ?";
List<List> argsList = new ArrayList<List>();
try{
DruidDBUtil.startTransaction();
List list1 = new ArrayList();
list1.add(number*-1);
list1.add(sourceId);
List list2 = new ArrayList();
list2.add(number);
list2.add(destId);
argsList.add(list1);
argsList.add(list2);
DruidDBUtil.executeBatch(sql,argsList);
DruidDBUtil.commit();
DruidDBUtil.endTransaction();
return true;
}catch(Exception ex){
ex.printStackTrace();
DruidDBUtil.rollback();
DruidDBUtil.commit();
return false;
}finally{
DruidDBUtil.closeAll();
}
}
//登录
public Account login(String cid, String password) {
Account account = null;
String sql = "select * from account where cid=? and password=?";
ResultSet rs = null;
List argsList = new ArrayList();
argsList.add(cid);
argsList.add(password);
try {
rs = DruidDBUtil.executeQuery(sql, argsList);
if (rs.next()) {
account = new Account();
account.setCid(rs.getString("cid"));
account.setName(rs.getString("name"));
account.setPassword(rs.getString("password"));
account.setBalance(rs.getInt("balance"));
account.setModifydate(rs.getString("modifydate"));
}
return account;
} catch (Exception ex) {
ex.printStackTrace();
return null;
}
}
//根据银行开户查询余额
public int queryBalanceByCid(String cid) {
ResultSet rs = null;
String sql = "select balance from account where cid=? ";
List argsList = new ArrayList();
argsList.add(cid);
try {
rs = DruidDBUtil.executeQuery(sql, argsList);
if (rs.next()) {
return rs.getInt("balance");
}
return -1;
} catch (Exception ex) {
ex.printStackTrace();
return -1;
}
}
//查询卡号是否存在
public boolean checkAccountIdExists(String cid){
ResultSet rs = null;
String sql = "select * from account where cid=? ";
List argsList = new ArrayList();
argsList.add(cid);
try {
rs = DruidDBUtil.executeQuery(sql, argsList);
if (rs.next()) {
return true;
}
return false;
} catch (Exception ex) {
ex.printStackTrace();
return false;
}
}
}
5.设计程序的主界面类
package com.oracle.jdbc.demo.atm;
import com.oracle.jdbc.demo.domain.Account;
import java.util.Scanner;
public class AtmDemo {
public static Scanner sc = new Scanner(System.in);
public static int choice;
public static AccountService accountService = new AccountService();
public static Account currentAccount = null; //当前的银行账号
//主界面
public static void showMenu() {
System.out.println("**************XXX银行ATM系统**************");
System.out.println("1.开户");
System.out.println("2.存款");
System.out.println("3.取款");
System.out.println("4.转账");
System.out.println("5.退出系统");
System.out.println("************************************");
System.out.println("请选择(1-5):");
choice = sc.nextInt();
}
public static void main(String[] args) {
showMenu();
while (true) {
if (choice == 5) {
break;
}
switch (choice) {
case 1:
if ((currentAccount = accountService.createAccount()) != null) {
System.out.println("恭喜您,开户成功");
System.out.println(currentAccount);
}
break;
case 2:
String cid, password;
int money;
System.out.println("请输入您的银行卡号:");
cid = sc.next();
System.out.println("请输入您的取款密码:");
password = sc.next();
if ((currentAccount = accountService.login(cid, password)) != null) {
System.out.println("请输入存款金额:");
money = sc.nextInt();
if (accountService.deposit(currentAccount, money)) {
System.out.println("存款成功!");
System.out.println("存款余额是:" + accountService.queryBalanceByCid(cid) + " 元");
}
} else {
System.out.println("对不起,该账号不存在!");
}
break;
case 3:
System.out.println("请输入您的银行卡号:");
cid = sc.next();
System.out.println("请输入您的取款密码:");
password = sc.next();
if ((currentAccount = accountService.login(cid, password)) != null) {
System.out.println("请输入取款金额:");
money = sc.nextInt();
if (accountService.withdraw(currentAccount, money)) {
System.out.println("取款成功!");
System.out.println("存款余额是:" + accountService.queryBalanceByCid(cid) + " 元");
}
} else {
System.out.println("对不起,该账号不存在!");
}
break;
case 4:
System.out.println("请输入您的银行卡号:");
cid = sc.next();
System.out.println("请输入您的取款密码:");
password = sc.next();
if ((currentAccount = accountService.login(cid, password)) != null) {
System.out.println("请输入转账卡号:");
String destId = sc.next();
if (accountService.checkAccountIdExists(destId)) {
System.out.println("请输入转账金额:");
money = sc.nextInt();
if (accountService.transfer(cid, destId, money)) {
System.out.println("转账成功!");
System.out.println("存款余额是:" + accountService.queryBalanceByCid(cid) + " 元");
} else {
System.out.println("转账失败!");
}
}else{
System.out.println("转账卡号不存在!");
}
}else{
System.out.println("对不起,该账号不存在!");
}
break;
}
showMenu();
}
System.out.println("感谢您的使用,byebye!");
}
}
程序执行效果:
