项目结构:
其中新创建的lib包需要将网上下载好的数据库对应版本复制进去。后续还需再导入,具体的导入方式在另一篇JDBC六部曲中会详细体现。Java代码使用IDEA编辑器编辑。
需要用到的数据库表格(使用数据库编译软件workbench):
文件AtmDao中内容:
package dao;
import domain.Atm;
import java.sql.*;
public class AtmDao {
// Dao层(持久层)。底层JDBC
// 全是纯粹的JDBC读写连接数据库操作,没有任何逻辑 对于atm表格的新增,修改,删除,查询单条
// 增删改——>几乎一致——>可优化(SQL 参数)
// 查询方法与别的类比——>每个类都有查询且几乎一致——>SQL 参数 处理结果
// 出现框架 ————————> MyBatis Hibernate ——————> 持久层框架,负责读写数据库。
//设计一个方法,负责将弄一条记录删除
public void delete(String aname){
Connection conn = null;
Statement stat = null;
try {
//1.jdbc连接
String className = "com.mysql.jdbc.Driver"; //5.x版本。 8.x版本:com.mysql.cj.jdbc.Driver
String url = "jdbc:mysql://localhost:3306/atm?characterEncoding=UTF-8";//若有中文字符一定要加 ?characterEncoding=UTF-8
// 数据库版本和驱动包版本不一致,可能会出现红色提示(不影响)。若想去掉提示,则加:?useSSL=true
// 5.0x版本:jdbc:mysql://ip:port/database名 8.x版本:jdbc:mysql://ip:port/database名?serverTimezone=CST(时区)
String user = "zzt";
String password = "123";
//可修改密码和余额。
String sql = "DELETE FROM ATM WHERE ANAME='"+aname+"'";
Class.forName(className);
conn = DriverManager.getConnection(url,user,password);
stat = conn.createStatement();
//2.执行一条update语句
stat.executeUpdate(sql);
} catch (Exception e) {
e.printStackTrace();
} finally {
//两次关闭分开关,保证程序健壮性。
try {
if (stat!=null) {
stat.close();
}
} catch (SQLException e) {
e.printStackTrace();
}
try {
if (conn!=null) {
conn.close();
}
} catch (SQLException e) {
e.printStackTrace();
}
}
}
//设计一个方法 负责将一行新的记录(注册新人)写入数据库
public void insert(Atm aname){
Connection conn = null;
Statement stat = null;
try {
//1.jdbc连接
String className = "com.mysql.jdbc.Driver";
String url = "jdbc:mysql://localhost:3306/atm?characterEncoding=UTF-8";//若有中文字符一定要加 ?characterEncoding=UTF-8
// 数据库版本和驱动包版本不一致,可能会出现红色提示(不影响)。若想去掉提示,则加:?useSSL=true
String user = "zzt";
String password = "123";
//可修改密码和余额。
String sql = "INSERT INTO ATM VALUES('"+aname.getAname()+"','"+aname.getApassword()+"',"+aname.getAbalance()+")";
Class.forName(className);
conn = DriverManager.getConnection(url,user,password);
stat = conn.createStatement();
//2.执行一条update语句
stat.executeUpdate(sql);
} catch (Exception e) {
e.printStackTrace();
} finally {
//两次关闭分开关,保证程序健壮性。
try {
if (stat!=null) {
stat.close();
}
} catch (SQLException e) {
e.printStackTrace();
}
try {
if (conn!=null) {
conn.close();
}
} catch (SQLException e) {
e.printStackTrace();
}
}
}
//很多方法中程序一致,出现代码冗余。 设计一个方法,专门做重复的事情,可以复用。
//存款和取款方法出现代码冗余 参数——人名+存款金额;人名+取款金额 将存和取的运算用另一个方法实现,保证此方法的广泛应用。
//jdbc流程(连接数据库,做写“更新”操作)+修改方法,分开。 参数——Atm 返回值——void
//转账,修改密码 也是做修改。
public void update(Atm atm){
//将数据库信息修改更新 update
Connection conn = null;
Statement stat = null;
try {
//1.jdbc连接
String className = "com.mysql.jdbc.Driver";
String url = "jdbc:mysql://localhost:3306/atm?characterEncoding=UTF-8";//若有中文字符一定要加 ?characterEncoding=UTF-8
// 数据库版本和驱动包版本不一致,可能会出现红色提示(不影响)。若想去掉提示,则加:?useSSL=true
String user = "zzt";
String password = "123";
//可修改密码和余额。
String sql = "UPDATE ATM SET APASSWORD = '"+atm.getApassword()+"',ABALANCE = "+atm.getAbalance()+" WHERE ANAME = '"+atm.getAname()+"';";
Class.forName(className);
conn = DriverManager.getConnection(url,user,password);
stat = conn.createStatement();
//2.执行一条update语句
stat.executeUpdate(sql);
} catch (Exception e) {
e.printStackTrace();
} finally {
//两次关闭分开关,保证程序健壮性。
try {
if (stat!=null) {
stat.close();
}
} catch (SQLException e) {
e.printStackTrace();
}
try {
if (conn!=null) {
conn.close();
}
} catch (SQLException e) {
e.printStackTrace();
}
}
}
//登录和查询方法出现代码冗余 参数——都有用户名;返回值——不确定
public Atm selectOne(String aname){
Atm atm = null;
String classname = "com.mysql.jdbc.Driver";
String url = "jdbc:mysql://localhost:3306/atm?characterEncoding=UTF-8";//若有中文字符一定要加 ?characterEncoding=UTF-8
// 数据库版本和驱动包版本不一致,可能会出现红色提示(不影响)。若想去掉提示,则加:?useSSL=true
String user = "zzt";
String password = "123";
String sql = "SELECT ANAME,APASSWORD,ABALANCE FROM ATM WHERE ANAME = '"+aname+"'";
Connection conn = null;
Statement stat = null;
ResultSet rs = null;
try {
Class.forName(classname);
conn = DriverManager.getConnection(url,user,password);
stat = conn.createStatement();
rs = stat.executeQuery(sql);
if (rs.next()){
//证明用户名存在,查询到了一行记录。返回值是什么!?将结果集内的数据取出来,存在一个容器(数组,集合,对象domain)里,并返回。
atm = new Atm(); //懒加载机制
atm.setAname(rs.getString("aname"));
atm.setApassword(rs.getString("apassword"));
atm.setAbalance(rs.getFloat("abalance"));
}
//关闭放在此处不安全,因为前面有可能出错而导致不能运行至关闭。
} catch (Exception e) {
e.printStackTrace();
} finally {
//三次关闭分别关,保证程序健壮性。
try {
if (rs!=null) {
rs.close();
}
} catch (SQLException e) {
e.printStackTrace();
}
try {
if (stat!=null) {
stat.close();
}
} catch (SQLException e) {
e.printStackTrace();
}
try {
if (conn!=null) {
conn.close();
}
} catch (SQLException e) {
e.printStackTrace();
}
}
return atm;
}
// 以上的是纯粹的JDBC读写数据库操作,没有逻辑。
}
文件Atm中内容:
package domain;
public class Atm {
//此类叫domain实体类。 只是为了存储表格中的数据。
//类 表
//对象 行 “小容器”
//属性 列
//类型 类型
private String aname;
private String apassword;
private Float abalance; //因为值可能为空。基本类型不能存放空值,引用类型可以。
public Atm(){}
public Atm(String aname, String apassword, Float abalance) { //创建快捷方式:右键——>Generate——>Constructor——>Ctrl全选
this.aname = aname;
this.apassword = apassword;
this.abalance = abalance;
}
//创建快捷方式:右键——> Generate ——> Getter and Setter ——> Ctrl全选
public String getAname() {
return aname;
}
public void setAname(String aname) {
this.aname = aname;
}
public String getApassword() {
return apassword;
}
public void setApassword(String apassword) {
this.apassword = apassword;
}
public Float getAbalance() {
return abalance;
}
public void setAbalance(Float abalance) {
this.abalance = abalance;
}
}
文件AtmService中内容:
package service;
import dao.AtmDao;
import domain.Atm;
public class AtmService {
// Service层(业务层) 做业务逻辑,需要持久层(Dao层)的支持,则需要底层对象作为属性。
private AtmDao dao = new AtmDao();
//或用自定义注解:
//@MyAnnotation("dao.AtmDao")
//private AtmDao dao;
// -------------------------------MVC分层思想(M数据模型:数据存储domain,数据处理service,数据读写dao)---------------------------------------
//以下方法都是处理业务逻辑。比较 判断 计算。没有任何一个方法可以看到数据读写数据库操作(JDBC)
//登录
public String login(String aname,String apassword){
String result = "用户名或密码错误!";
Atm atm = dao.selectOne(aname);
if (atm!=null){
if (atm.getApassword().equals(apassword)){
result = "登录成功!";
}
}
return result;
}
//查询
public float cha(String aname){
float result = 0;
Atm atm = dao.selectOne(aname);
return atm.getAbalance();
//也可简写成 return this.selectOne(aname).getAbalance();
}
//存款
public void cun(String aname,float cunMoney){
//找原始数据,找atm = selectOne读。
Atm atm = dao.selectOne(aname);
//此方法只需要做修改的事情,负责逻辑运算。
atm.setAbalance(atm.getAbalance()+cunMoney);
//最终数据交给update方法。
dao.update(atm);
}
//取款
public void qu(String aname,float quMoney){
//找原始数据,找atm = selectOne读。
Atm atm = dao.selectOne(aname);
//此方法只需要做修改的事情,负责逻辑运算。
if (atm.getAbalance()>=quMoney) {
atm.setAbalance(atm.getAbalance() - quMoney);
dao.update(atm);
}else {
System.out.println("对不起,余额不足!");
}
//最终数据交给update方法。
}
//转账
public void zhuan(String outName,String inName,float zhuanMoney){
// this.qu(outName,zhuanMoney);
// this.cun(inName,zhuanMoney);
Atm outAtm = dao.selectOne(outName);
Atm inAtm = dao.selectOne(inName);
if (outAtm.getAbalance()>=zhuanMoney){
outAtm.setAbalance(outAtm.getAbalance()-zhuanMoney);
inAtm.setAbalance(inAtm.getAbalance()+zhuanMoney);
dao.update(outAtm);
dao.update(inAtm);
//提交事务。
}else {
System.out.println("对不起,余额不足!");
}
}
//开户
public void kai(String aname,String apassword,float abalance){
Atm atm = new Atm(aname,apassword,abalance);
dao.insert(atm);
}
//销户
public void xiao(String aname){
Atm atm = dao.selectOne(aname);
if (atm!=null){
dao.delete(aname);
}
}
}
文件TestMain中内容:
package test;
import service.AtmService;
import java.util.Scanner;
public class TestMain {
public static void main(String[] args){
Scanner input = new Scanner(System.in);
AtmService ta = new AtmService();
System.out.println("请输入用户名:");
String aname = input.nextLine();
System.out.println("请输入密码:");
String apassword = input.nextLine();
String result = ta.login(aname,apassword);
if (result.equals("登录成功!")){
System.out.println("欢迎"+aname+"进入ATM银行系统!");
while (true) {
System.out.println(aname+"用户,请输入操作选项:");
System.out.println("查询输入1,存款输入2,取款输入3,转账输入4,开户输入5,销户输入6,退出输入0。。");
String option = input.nextLine();
if (option.equals("0")) {
break;
}
switch (option) {
case "1":
float abalance = ta.cha(aname);
System.out.println("尊敬的" + aname + "用户,您的可用余额为:" + abalance);
break;
case "2":
System.out.println("请输入存款金额:");
String cunMoney = input.nextLine();
ta.cun(aname, Float.parseFloat(cunMoney));
break;
case "3":
System.out.println("请输入取款金额:");
String quMoney = input.nextLine();
ta.qu(aname, Float.parseFloat(quMoney));
break;
case "4":
System.out.println("请输入转账用户:");
String inName = input.nextLine();
System.out.println("请输入转账金额:");
String zhuanMoney = input.nextLine();
ta.zhuan(aname,inName,Float.parseFloat(zhuanMoney));
break;
case"5":
System.out.println("请输入需要开户人姓名:");
String name = input.nextLine();
System.out.println("请设置账户密码:");
String password = input.nextLine();
System.out.println("输入需要存入金额:");
float money = input.nextFloat();
ta.kai(name,password,money);
break;
case"6":
System.out.println("确定销除当前账户?true or false");
boolean rs = input.nextBoolean();
if (rs == true){
ta.xiao(aname);
System.out.println("请选择退出:0!");
}
break;
}
}
}else{
System.out.println(result);
}
}
}