基于JDBC的账务管理系统

一、项目介绍

1.1 项目目标

	本项目为JAVAEE基础和数据库的综合项目,包含了若干个知识点,达到将从基础班到现在所学的知识综合使用,提高了我们对项目的理解与知识点的运用。

熟练View层、Service层、Dao层之间的方法相互调用操作

熟练使用工具类操作数据库表完成增删改查以及登录的功能

通过本项目,让我们了解公司项目开发的流程,充分的掌握项目需求分析、设计与功能的代码实现。提高同学们独立分析需求与功能实现的能力。

二、项目环境搭建

2.1 数据准备

/*
  创建账务管理的数据库
*/
CREATE DATABASE account CHARACTER SET utf8;
USE account;

/*
 用户表
 字段:
	用户id
	用户名 username
	密码 password
*/
CREATE TABLE ac_user(
	id INT PRIMARY KEY AUTO_INCREMENT,
	username VARCHAR(20),
	password VARCHAR(20),
	isManager int	-- 1.管理员;0:普通用户;
);
INSERT ac_user(username,password,isManager)
values('admin','admin',1),
('user','user',0)
/*
  创建数据表,表名账务
  字段,列
  主键
  分类名称  可变字符
  金额  double
  支付方式  可变字符 (支付,收入方法)
  创建日期 date
  账务描述 可变字符
*/
CREATE TABLE ac_account(   
   id INT PRIMARY KEY AUTO_INCREMENT, -- 主键   
   sortname VARCHAR(200),-- 分类名称      
   money decimal(10,2),-- 金额   
   type VARCHAR(100),-- 支付方式   
   createtime DATE,-- 创建日期   
   desp  VARCHAR(1000)-- 账务描述
);
SELECT * FROM ac_account;

-- 写入测试的数据
INSERT  INTO ac_account(id,sortname,money,type,createtime,desp) VALUES (1,'吃饭支出',247,'交通银行','2016-03-02','家庭聚餐');
INSERT  INTO ac_account(id,sortname,money,type,createtime,desp) VALUES (2,'工资收入',12345,'现金','2016-03-15','开工资了');
INSERT  INTO ac_account(id,sortname,money,type,createtime,desp) VALUES (3,'服装支出',1998,'现金','2016-04-02','买衣服');
INSERT  INTO ac_account(id,sortname,money,type,createtime,desp) VALUES (4,'吃饭支出',325,'现金','2016-06-18','朋友聚餐');
INSERT  INTO ac_account(id,sortname,money,type,createtime,desp) VALUES (5,'股票收入',8000,'工商银行','2016-10-28','股票大涨');

2.2 技术选型

	每个项目都要使用一些已经成熟的技术,它们通常是由一些专业组织或团队所提供的开源免费技术。在今后的学习过程中,我们会逐渐对这些专业组织有所了解。本项目中使用的技术如下:
  • Druid
    Druid数据连接池依赖该jar包
    • druid-1.0.9.jar
  • 数据库驱动
    MySQL的JDBC驱动包,用JDBC连接MySQL数据库必须使用该JAR包。
    • mysql-connector-java-5.1.37-bin.jar
      2.3 JDBC工具类
      每个项目都会用到一些工具类,本项目也不例外。JDBC工具类之前也讲过,在这里就不在详细描述!
package cn.yh.util;

import com.alibaba.druid.pool.DruidDataSourceFactory;

import javax.sql.DataSource;
import java.io.IOException;
import java.io.InputStream;
import java.sql.*;
import java.util.Properties;

/**
 * druid的通用类;
 * 1.导入jar和配置文件;
 * 2.创建一个通用类,static,读取文件;
 * 3.工厂来获取?连接池--->连接;
 */
public class DruidUtil {
    //成员变量
    static DataSource ds=null;
    static Connection conn=null;
    static PreparedStatement pst=null;
    static ResultSet rs=null;

    static {
        try {
            InputStream fis = DruidUtil.class.getClassLoader().getResourceAsStream("druid.properties");
            //FileInputStream fis=new FileInputStream("src/db.properties");
            Properties prop=new Properties();
            prop.load(fis);
            //通过工厂,来获取连接池对象ds
             ds= DruidDataSourceFactory.createDataSource(prop);
        } catch (IOException e) {
            e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    //获取连接:DriverManager
    public static Connection getConnection(){
        try {
            conn= ds.getConnection();
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        }
        return conn;
    }

    //3.通用的增删改,easy;注意理解思想:可变参;由于也不清楚,具体的类型,所以,写Object; ... :可变参;
    //可变参:本质是数组;注意:当没有参数的时候,可以直接写update(sql,null),update(sql);
    public static int update(String sql,Object ... params){
        int result=0;
        //3.2 获取预编译语句对象;
        try {
            conn=getConnection(); //从本类来调用一下;
            System.out.println(conn);
            pst = conn.prepareStatement(sql);
            //针对?赋值;
            if(params!=null){
                for (int i = 0; i < params.length; i++) {
                    pst.setObject(i+1,params[i]);
                }
            }
            result=pst.executeUpdate();
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        }finally {
            close(null,pst,conn);
        }
        return result;
    }
    //4.通用封装查询

    //5.通用封装等;

    //6.
    public static void close(ResultSet r, Statement s, Connection c){
        if (c!=null){
            try {
                c.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
        if (r!=null){
            try {
                r.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
        if (s!=null){
            try {
                s.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }
}

2.4 项目分层(分包)

项目分层,分包好处是方便管理,各自负责各自的功能,也方便我们找错改问题!

  • view层作用: 视图层,即项目中的界面
  • controller层作用: 控制层, 获取界面上的数据,为界面设置数据; 将要实现的功能交给业务层处理
  • service层作用(可省略): 业务层, 功能的实现, 与controller控制层和数据访问层DAO交互, 将对数据库的操作交给DAO数据访问层来处理
  • dao层作用: 数据访问层, 用来操作数据库表的数据
  • entity 实体包: 存放JavaBean
  • util工具包:存放项目中使用到的工具类
  • test 测试包: 存放项目功能测试的代码
    2.5 工程创建
    基于JDBC的账务管理系统_第1张图片
    三、相关类编写

3.1 相关类创建
主界面类:

public class TestUtil {
    @Test
    public void test01(){
        MainView mv=new MainView();
        mv.login();
    }
}

MainView类

package cn.yh.test;

import cn.yh.dao.AccountDao;
import cn.yh.dao.AccountDaoImpl;
import cn.yh.dao.UserDao;
import cn.yh.dao.UserDaoImpl;
import cn.yh.entity.Account;
import cn.yh.entity.User;


import java.util.Date;
import java.util.List;
import java.util.Scanner;

/*
* 4.主界面的类;这里实现类,是其成员变量;
* */
public class MainView {
    UserDao userDao=new UserDaoImpl();
    AccountDao accountDao=new AccountDaoImpl();
    Scanner sc=new Scanner(System.in);  //为了后续,有很多的输入,直接在外面设计sc控制台输入为成员变量;

    //接下来是界面的设计;简单的界面;操作:登录;其他查询?
    //4.1构建第一个界面;
    public void login(){
        System.out.println("----------------金算盘账务管理系统----------------");
        int i=3;
        while(i>0) {
            System.out.println("请输入账户:");
            String username = sc.nextLine();
            System.out.println("请输入密码:");
            String password = sc.nextLine();
            i--;
            //调用实现类:
            User user = userDao.selectUser(username, password);
            if (user != null) {     //登录
                menu();
            } else {
                if(i==0)break;
                System.out.println("账户名和密码不对!,还剩机会"+(i)+"机会");  //如果不对,则继续输入,升级改进,加循环;!
            }
        }
    }
    //4.2 构建第二个界面;针对账户,做选择操作;汇总sum(money) ;其他人;当前账户的信息,sum(money)
    public void menu(){
        while(true){
            System.out.println("*******************账务管理系统*******************");
            System.out.println("请选择您的操作:1.查看余额 2.存款 3.取款 4.转账 5.查看明细 6.修改密码 7.退出");
            int choice=sc.nextInt(); //获取方式,和nextLine() 以回车换行读取 ;nextInt();
            switch (choice){
                case 1:
                    selectBalance();break;
                case 2:
                    saveMoney();break;
                case 3:
                    drawMoney();break;
                case 4:
                    transferMoney();break;
                case 5:
                    selectDetails();break;
                case 6:
                    editPwd();break;
                case 7:
                    System.exit(0);
                default:
                    break;
            }
        }

    }
    /**
     * 修改自己的密码;由于这里是针对用户的操作,需要userDao增加方法;
     */
    private void editPwd() {

    }

    /**
     * 4.7 查看明细界面;一个是查看所有详情信息;另外一个是按时间查询(开始和结束时间);
     */
    private void selectDetails() {
        System.out.println("---------------账务管理系统---------------------");
        System.out.println("请选择您的操作:1.查看所有信息 2.按时间查询 ");
        int choice=sc.nextInt();
        switch (choice){
            case 1:
                selectAll();break;
            case 2:
                selectByDate();break;
        }

    }
    //4.7.2条件查询;升级:
    // 4.7.3 根据所有收入%模糊查询;  所有奖金;
    // 4.7.4查询收入一共有多少前;支出一共有多少钱;group by分组; mysql
    // 4.7.5 排序;查询今年支出排序;order by

    // 子业务: 需要输入一个开始时间,一个结束时间;
    //输入值,由selectByDate()来接收值;
    private void selectByDate() {
        sc.nextLine();
        System.out.println("请输入开始时间:");
        String startTime=sc.nextLine();
        System.out.println("请输入结束时间:");
        String endTime=sc.nextLine();
        //去调用根据时间的查询;
        List<Account> accountList = accountDao.selectByDate(startTime, endTime);
        accountList.forEach(a->{
            System.out.println(a.getId()+"\t"+a.getSortname()+"\t"+a.getMoney()+"\t"+a.getType());
        });
    }

    //4.7.1查看所有信息;查看所有账户account的信息,需要去调用accountDao信息;
    private void selectAll() {
        List<Account> accountList = accountDao.selectAll();
//        for (Account a : accountList) {
//            System.out.println(a.getId()+"\t"+a.getTypeName()+"\t"+a.getMoney()+"\t"+a.getType());
//        }
        //stream forEach 兰布达;
        accountList.forEach(a->{
            System.out.println(a.getId()+"\t"+a.getSortname()+"\t"+a.getMoney()+"\t"+a.getType());
        });
    }

    //4.6转账界面
    private void transferMoney() {
    }

    //4.5取款界面
    private void drawMoney() {
    }

    //4.4 存款界面;去对账户做处理;
    private void saveMoney() {
        System.out.println("---------------账务管理系统---------------------");
        sc.nextLine();
        System.out.println("请输入存款的类型:");
        String typeName=sc.nextLine();
        System.out.println("请输入存款金额:");
        int money=sc.nextInt();
        sc.nextLine();
        System.out.println("请输入存款方式:(银行、支付宝、微信、现金)");  //1.xx银行;2.支付宝;3.微信;4.现金
        String type=sc.nextLine();
        System.out.println("请输入备注信息:");
        String desc=sc.nextLine();
        //去调用实体类的存款方法;
        //去对对象做一个封装;a:是一个账户对象;

        //这里需要重点来理解一下,我用的当前时间:是java系统的时间;java.util包;
        long nowTime = new Date().getTime();
        //存到数据库的时候,java.sql.Date
        Account a=new Account(typeName,type,money,new java.sql.Date(nowTime),desc);
        int result=accountDao.saveMoney(a); //将a作为参数传递过去;
        if(result>0){
            System.out.println("存款成功!");
            //去哪里?
        }
    }

    //4.3 第三个界面;查看余额;
    private void selectBalance() {
        double v = accountDao.selectBalance();
        System.out.println("您的余额是:"+v);
    }


}

实体类:

package cn.yh.entity;
//2.实体类User
public class User {
    private int id;
    private String userName;
    private String password;

    public User() {
    }

    public User(int id, String userName, String password) {
        this.id = id;
        this.userName = userName;
        this.password = password;
    }

    public User(String userName, String password) {
        this.userName = userName;
        this.password = password;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getUserName() {
        return userName;
    }

    public void setUserName(String userName) {
        this.userName = userName;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    @Override
    public String toString() {
        return "User{" +
                "id=" + id +
                ", userName='" + userName + '\'' +
                ", password='" + password + '\'' +
                '}';
    }
}

Account类

package cn.yh.entity;

import java.sql.Date;  //后续要存到数据库;sql.Date

//2.2实体类Account
public class Account {
    private int id;
    private String sortname;
    private String type;
    private double money;
    private Date createTime;
    private String description;

    public Account() {
    }

    public Account(String sortname, String type, double money, Date createTime, String description) {
        this.sortname = sortname;
        this.type = type;
        this.money = money;
        this.createTime = createTime;
        this.description = description;
    }

    public Account(int id, String sortname, String type, double money, Date createTime, String description) {
        this.id = id;
        this.sortname = sortname;
        this.type = type;
        this.money = money;
        this.createTime = createTime;
        this.description = description;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getSortname() {
        return sortname;
    }

    public void setSortname(String sortname) {
        this.sortname = sortname;
    }

    public String getType() {
        return type;
    }

    public void setType(String type) {
        this.type = type;
    }

    public double getMoney() {
        return money;
    }

    public void setMoney(double money) {
        this.money = money;
    }

    public Date getCreateTime() {
        return createTime;
    }

    public void setCreateTime(Date createTime) {
        this.createTime = createTime;
    }

    public String getDescription() {
        return description;
    }

    public void setDescription(String description) {
        this.description = description;
    }

    @Override
    public String toString() {
        return "Account{" +
                "id=" + id +
                ", typeName='" + sortname + '\'' +
                ", type='" + type + '\'' +
                ", money=" + money +
                ", createTime=" + createTime +
                ", description='" + description + '\'' +
                '}';
    }
}

数据层:

package cn.yh.dao;

import cn.yh.entity.Account;

import java.util.List;

//3.3 接口;Account的CRUD;
public interface AccountDao {
    //完善存款方法;
    public int saveMoney(Account a);
    //增加一个查看所有账户信息的方法;
    public List<Account> selectAll();
    //增加一个方法,根据时间来查询信息的方法;
    public List<Account> selectByDate(String startTime,String endTime);
    //里面增加一个查询余额的方法;
    public double selectBalance();
    //根据cardid来查询的方法即可;
}

实现类:

package cn.yh.dao;

import cn.yh.entity.Account;
import cn.yh.util.DruidUtil;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

//3.4创建 接口的实现类;
public class AccountDaoImpl implements AccountDao {
    //类的成员变量;初始的时候,设置为null,在方法调用的时候去赋值,可以节省内存空间 ;
    Connection conn=null;
    PreparedStatement pst=null;
    ResultSet rs=null;

    //传递的参数在Account对象a里面;
    @Override
    public int saveMoney(Account a) {
        String sql="insert ac_account(sortname,type,money,createtime,description)values(?,?,?,?,?)";
        Object[]params={a.getSortname(),a.getType(),a.getMoney(),a.getCreateTime(),a.getDescription()};
        return DruidUtil.update(sql,params);
    }
    //实现这个查看所有信息的方法;
    @Override
    public List<Account> selectAll() {
        //获取链接;
       conn= DruidUtil.getConnection();
        List<Account>accountList=null;
        //语句对象;
        try {
            pst=conn.prepareStatement("select * from ac_account");
            rs=pst.executeQuery();
            accountList=new ArrayList<>();  //创建实例;
            //list:里面存放的是Account的集合;每个Account对象
            while(rs.next()){
                Account a=new Account();  //创建对象 ,下面几行是赋值;
                a.setId(rs.getInt("id"));
                a.setSortname(rs.getString("typeName"));
                a.setType(rs.getString("type"));
                a.setMoney(rs.getDouble("money"));
                a.setCreateTime(rs.getDate("createTime"));
                a.setDescription(rs.getString("description"));
                accountList.add(a);
            }
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        } finally {
            DruidUtil.close(rs,pst,conn);
        }
        return accountList;
    }

    @Override
    public List<Account> selectByDate(String startTime, String endTime) {
        conn=DruidUtil.getConnection();
        List<Account> accountList=null;
        try {
            pst=conn.prepareStatement("select * from ac_account where createTime between ? and ?"); //复习sql
            //需要赋值给?
            pst.setString(1,startTime);
            pst.setString(2,endTime);
            rs=pst.executeQuery();  //结果集对象获取;
            accountList=new ArrayList<>();  //作用域,在try{}有效;  100万亿津巴布韦币;
            Account a=null;
            while(rs.next()){
                a=new Account();
                a.setId(rs.getInt("id"));
                a.setSortname(rs.getString("typeName"));
                a.setType(rs.getString("type"));
                a.setMoney(rs.getDouble("money"));
                a.setCreateTime(rs.getDate("createTime"));
                a.setDescription(rs.getString("description"));
                //添加到集合;
                accountList.add(a);
            }
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        } finally {
            DruidUtil.close(rs,pst,conn);
        }
        return accountList;
    }
    /*
        后续如果要扩充,根据cardid,来余额
        selectBalance(String cardid){}
        select sum(money) from ac_account group by cardid
     */
    @Override
    public double selectBalance() {
        String sql="select sum(money) from ac_account";
        conn=DruidUtil.getConnection();
        double result=0.0;
        try {
            pst=conn.prepareStatement(sql);
            rs = pst.executeQuery();
            //只查询一条数据;单行单列;
            if(rs.next()){
                result =rs.getDouble(1);
            }
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        } finally {
            DruidUtil.close(rs,pst,conn);
        }
        return result;
    }
}

UserDao接口

package cn.yh.dao;

import cn.yh.entity.User;

//3.创建接口:针对User表的操作;CRUD
public interface UserDao {
    //3.3.1第一个方法,是查询;User user;参数就是刚才的用户名和密码;
    public User selectUser(String username,String password);
}

实现类:

package cn.yh.dao;

import cn.yh.entity.User;
import cn.yh.util.DruidUtil;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

//3.2 UserDao的实现类;这里暂时不考虑,用户名和密码,重复;
public class UserDaoImpl implements UserDao{
    //让三个接口对象为成员变量,可以在finally访问;
    Connection conn=null;
    PreparedStatement pst=null;
    ResultSet rs=null;
    @Override
    public User selectUser(String username, String password) {
        User user=null;
        String sql="select * from ac_user where username=? and password=?";
        try {
            conn= DruidUtil.getConnection();    //
            pst= conn.prepareStatement(sql);
            pst.setString(1,username);
            pst.setString(2,password);
            rs= pst.executeQuery();

            if(rs.next()){
                user=new User();
                user.setId(rs.getInt("id"));
                user.setUserName(rs.getString("username"));
                user.setPassword(rs.getString("password"));
            }
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        }finally {
            DruidUtil.close(rs,pst,conn);
        }
        return user;
    }
}

618,清华社 IT BOOK 多得图书活动开始啦!活动时间为 2023 年 6 月 7 日至 6 月 18 日,清华
社为您精选多款高分好书,涵盖了 C++、Java、Python、前端、后端、数据库、算法与机器学习等多
个 IT 开发领域,适合不同层次的读者。全场 5 折,扫码领券更有优惠哦!快来京东点击链接 IT BOOK
多得(或扫描京东二维码)查看详情吧!

基于JDBC的账务管理系统_第2张图片

你可能感兴趣的:(数据库,jdbc项目,jdbc,连接池,javase项目)