From 0eabc484a6068e446932106ab21bf49a2c6cb61a Mon Sep 17 00:00:00 2001 From: zyx <1029606625@qq.com> Date: Fri, 11 Nov 2022 00:34:24 +0800 Subject: [PATCH] =?UTF-8?q?2022/11/11=2000:33=20=E5=AE=8C=E6=88=90?= =?UTF-8?q?=E7=AC=AC11=E5=91=A8=E4=BD=9C=E4=B8=9A=E9=A2=982?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .idea/.gitignore | 8 + .idea/compiler.xml | 14 ++ .idea/dataSources.xml | 12 ++ .idea/encodings.xml | 7 + .idea/jarRepositories.xml | 20 ++ .idea/misc.xml | 14 ++ .idea/uiDesigner.xml | 124 +++++++++++++ .idea/vcs.xml | 6 + pom.xml | 41 +++++ src/main/java/cn/czyx007/week11/Driver.java | 45 +++++ .../java/cn/czyx007/week11/bean/Product.java | 24 +++ .../cn/czyx007/week11/bean/SaleDetail.java | 39 ++++ .../java/cn/czyx007/week11/bean/User.java | 24 +++ .../week11/controller/DataExportMenu.java | 37 ++++ .../controller/GoodMaintenanceMenu.java | 95 ++++++++++ .../czyx007/week11/controller/MainMenu.java | 174 ++++++++++++++++++ .../cn/czyx007/week11/dao/ProductDAO.java | 39 ++++ .../cn/czyx007/week11/dao/SaleDetailDAO.java | 52 ++++++ .../java/cn/czyx007/week11/dao/UserDAO.java | 32 ++++ .../week11/dao/impl/ProductDAOImpl.java | 111 +++++++++++ .../week11/dao/impl/SaleDetailDAOImpl.java | 166 +++++++++++++++++ .../czyx007/week11/dao/impl/UserDAOImpl.java | 82 +++++++++ .../week11/proxy/TransactionProxyFactory.java | 50 +++++ .../week11/service/ProductService.java | 16 ++ .../week11/service/SaleDetailService.java | 16 ++ .../czyx007/week11/service/UserService.java | 23 +++ .../service/impl/ProductServiceImpl.java | 23 +++ .../service/impl/SaleDetailServiceImpl.java | 19 ++ .../week11/service/impl/UserServiceImpl.java | 75 ++++++++ .../java/cn/czyx007/week11/utils/DBUtil.java | 78 ++++++++ .../cn/czyx007/week11/utils/ExcelUtil.java | 123 +++++++++++++ .../cn/czyx007/week11/utils/MenuUtil.java | 33 ++++ .../cn/czyx007/week11/utils/PasswordUtil.java | 36 ++++ .../cn/czyx007/week11/utils/ProductUtil.java | 90 +++++++++ .../java/cn/czyx007/week11/utils/TxtUtil.java | 84 +++++++++ src/main/resources/jdbc.properties | 4 + .../week11/test/TestUserServiceImpl.java | 24 +++ 37 files changed, 1860 insertions(+) create mode 100644 .idea/.gitignore create mode 100644 .idea/compiler.xml create mode 100644 .idea/dataSources.xml create mode 100644 .idea/encodings.xml create mode 100644 .idea/jarRepositories.xml create mode 100644 .idea/misc.xml create mode 100644 .idea/uiDesigner.xml create mode 100644 .idea/vcs.xml create mode 100644 pom.xml create mode 100644 src/main/java/cn/czyx007/week11/Driver.java create mode 100644 src/main/java/cn/czyx007/week11/bean/Product.java create mode 100644 src/main/java/cn/czyx007/week11/bean/SaleDetail.java create mode 100644 src/main/java/cn/czyx007/week11/bean/User.java create mode 100644 src/main/java/cn/czyx007/week11/controller/DataExportMenu.java create mode 100644 src/main/java/cn/czyx007/week11/controller/GoodMaintenanceMenu.java create mode 100644 src/main/java/cn/czyx007/week11/controller/MainMenu.java create mode 100644 src/main/java/cn/czyx007/week11/dao/ProductDAO.java create mode 100644 src/main/java/cn/czyx007/week11/dao/SaleDetailDAO.java create mode 100644 src/main/java/cn/czyx007/week11/dao/UserDAO.java create mode 100644 src/main/java/cn/czyx007/week11/dao/impl/ProductDAOImpl.java create mode 100644 src/main/java/cn/czyx007/week11/dao/impl/SaleDetailDAOImpl.java create mode 100644 src/main/java/cn/czyx007/week11/dao/impl/UserDAOImpl.java create mode 100644 src/main/java/cn/czyx007/week11/proxy/TransactionProxyFactory.java create mode 100644 src/main/java/cn/czyx007/week11/service/ProductService.java create mode 100644 src/main/java/cn/czyx007/week11/service/SaleDetailService.java create mode 100644 src/main/java/cn/czyx007/week11/service/UserService.java create mode 100644 src/main/java/cn/czyx007/week11/service/impl/ProductServiceImpl.java create mode 100644 src/main/java/cn/czyx007/week11/service/impl/SaleDetailServiceImpl.java create mode 100644 src/main/java/cn/czyx007/week11/service/impl/UserServiceImpl.java create mode 100644 src/main/java/cn/czyx007/week11/utils/DBUtil.java create mode 100644 src/main/java/cn/czyx007/week11/utils/ExcelUtil.java create mode 100644 src/main/java/cn/czyx007/week11/utils/MenuUtil.java create mode 100644 src/main/java/cn/czyx007/week11/utils/PasswordUtil.java create mode 100644 src/main/java/cn/czyx007/week11/utils/ProductUtil.java create mode 100644 src/main/java/cn/czyx007/week11/utils/TxtUtil.java create mode 100644 src/main/resources/jdbc.properties create mode 100644 src/test/java/cn/czyx007/week11/test/TestUserServiceImpl.java diff --git a/.idea/.gitignore b/.idea/.gitignore new file mode 100644 index 0000000..35410ca --- /dev/null +++ b/.idea/.gitignore @@ -0,0 +1,8 @@ +# 默认忽略的文件 +/shelf/ +/workspace.xml +# 基于编辑器的 HTTP 客户端请求 +/httpRequests/ +# Datasource local storage ignored files +/dataSources/ +/dataSources.local.xml diff --git a/.idea/compiler.xml b/.idea/compiler.xml new file mode 100644 index 0000000..c5daff3 --- /dev/null +++ b/.idea/compiler.xml @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/dataSources.xml b/.idea/dataSources.xml new file mode 100644 index 0000000..4a90b2c --- /dev/null +++ b/.idea/dataSources.xml @@ -0,0 +1,12 @@ + + + + + mysql.8 + true + com.mysql.cj.jdbc.Driver + jdbc:mysql://localhost:3306 + $ProjectFileDir$ + + + \ No newline at end of file diff --git a/.idea/encodings.xml b/.idea/encodings.xml new file mode 100644 index 0000000..aa00ffa --- /dev/null +++ b/.idea/encodings.xml @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/.idea/jarRepositories.xml b/.idea/jarRepositories.xml new file mode 100644 index 0000000..abb532a --- /dev/null +++ b/.idea/jarRepositories.xml @@ -0,0 +1,20 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml new file mode 100644 index 0000000..132404b --- /dev/null +++ b/.idea/misc.xml @@ -0,0 +1,14 @@ + + + + + + + + + + \ No newline at end of file diff --git a/.idea/uiDesigner.xml b/.idea/uiDesigner.xml new file mode 100644 index 0000000..2b63946 --- /dev/null +++ b/.idea/uiDesigner.xml @@ -0,0 +1,124 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml new file mode 100644 index 0000000..94a25f7 --- /dev/null +++ b/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/pom.xml b/pom.xml new file mode 100644 index 0000000..eda1a65 --- /dev/null +++ b/pom.xml @@ -0,0 +1,41 @@ + + + 4.0.0 + + cn.czyx007.week11 + week11-work2 + 1.0-SNAPSHOT + + + 8 + 8 + UTF-8 + + + + + mysql + mysql-connector-java + 8.0.30 + + + org.projectlombok + lombok + 1.18.20 + + + junit + junit + 4.13.2 + test + + + net.sourceforge.jexcelapi + jxl + 2.6.12 + + + + \ No newline at end of file diff --git a/src/main/java/cn/czyx007/week11/Driver.java b/src/main/java/cn/czyx007/week11/Driver.java new file mode 100644 index 0000000..e18f5b2 --- /dev/null +++ b/src/main/java/cn/czyx007/week11/Driver.java @@ -0,0 +1,45 @@ +package cn.czyx007.week11; + +import cn.czyx007.week11.bean.User; +import cn.czyx007.week11.controller.MainMenu; +import cn.czyx007.week11.proxy.TransactionProxyFactory; +import cn.czyx007.week11.service.UserService; +import cn.czyx007.week11.service.impl.UserServiceImpl; + +import java.util.Scanner; + +/** + * @author : 张宇轩 + * @createTime : 2022/11/10 + */ +public class Driver { + public static void main(String[] args) { + Scanner scanner = new Scanner(System.in); + UserService userService = (UserService) new TransactionProxyFactory(new UserServiceImpl()).getProxy(); + + System.out.println("欢迎使用超市收银系统,请登陆:"); + + int loginCnt = 0; + User user; + while (true) { + System.out.print("请输入用户名:"); + String username = scanner.nextLine(); + System.out.print("请输入密码:"); + String password = scanner.nextLine(); + + user = userService.login(username, password); + if (user != null) { + System.out.println("登录成功"); + MainMenu.mainMenu(user); + }else { + if (loginCnt++ < 2) { + System.out.println("用户名或密码不正确,请重新输入"); + } + else { + System.out.println("最多只能尝试 3 次"); + break; + } + } + } + } +} diff --git a/src/main/java/cn/czyx007/week11/bean/Product.java b/src/main/java/cn/czyx007/week11/bean/Product.java new file mode 100644 index 0000000..55084ad --- /dev/null +++ b/src/main/java/cn/czyx007/week11/bean/Product.java @@ -0,0 +1,24 @@ +package cn.czyx007.week11.bean; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * tproduct表对应的实体类 + * @author : 张宇轩 + * @createTime : 2022/11/10 + */ +@NoArgsConstructor +@AllArgsConstructor +@Data +public class Product { + //商品条形码 + private String barCode; + //商品名称 + private String productName; + //单价 + private Double price; + //供应商 + private String supply; +} diff --git a/src/main/java/cn/czyx007/week11/bean/SaleDetail.java b/src/main/java/cn/czyx007/week11/bean/SaleDetail.java new file mode 100644 index 0000000..0260493 --- /dev/null +++ b/src/main/java/cn/czyx007/week11/bean/SaleDetail.java @@ -0,0 +1,39 @@ +package cn.czyx007.week11.bean; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.text.SimpleDateFormat; +import java.util.Date; + +/** + * tsaledetail表对应的实体类 + * @author : 张宇轩 + * @createTime : 2022/11/10 + */ +@NoArgsConstructor +@AllArgsConstructor +@Data +public class SaleDetail { + //流水号 + private String lsh; + //商品条形码 + private String barCode; + //商品名称 + private String productName; + //商品单价 + private Double price; + //数量 + private Integer count; + //收银员 + private String operator; + //销售时间 + private Date saleTime; + + public void showInfo(){ + System.out.print(lsh + "\t" + productName + "\t"); + System.out.printf("% 8.2f\t% 4d\t% 8.2f\t",price,count,price*count); + System.out.print(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(saleTime) + "\t"); + } +} diff --git a/src/main/java/cn/czyx007/week11/bean/User.java b/src/main/java/cn/czyx007/week11/bean/User.java new file mode 100644 index 0000000..3da5f93 --- /dev/null +++ b/src/main/java/cn/czyx007/week11/bean/User.java @@ -0,0 +1,24 @@ +package cn.czyx007.week11.bean; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * tuser表对应的实体类 + * @author : 张宇轩 + * @createTime : 2022/11/10 + */ +@NoArgsConstructor +@AllArgsConstructor +@Data +public class User { + //用户登录名 + private String username; + //密码 sha1加密存储 + private String password; + //中文名 + private String chrName; + //用户角色 管理员/收银员 + private String role; +} diff --git a/src/main/java/cn/czyx007/week11/controller/DataExportMenu.java b/src/main/java/cn/czyx007/week11/controller/DataExportMenu.java new file mode 100644 index 0000000..7a0007d --- /dev/null +++ b/src/main/java/cn/czyx007/week11/controller/DataExportMenu.java @@ -0,0 +1,37 @@ +package cn.czyx007.week11.controller; + +import cn.czyx007.week11.utils.ExcelUtil; +import cn.czyx007.week11.utils.MenuUtil; +import cn.czyx007.week11.utils.TxtUtil; + +/** + * 数据导出菜单 + * @author : 张宇轩 + * @createTime : 2022/11/10 + */ +public class DataExportMenu { + public static void dataExportMenu(){ + while (true) { + int opt; + System.out.print("===超市销售信息导出====\n" + + "1、导出到 excel 文件\n" + + "2、导出到文本文件\n" + + "3、返回主菜单\n" + + "请选择(1-3):"); + do { + opt = MenuUtil.checkInput(1, 3); + } while (opt == -1); + + switch (opt) { + case 1://导出到excel文件 + ExcelUtil.exportDataToExcel(); + break; + case 2://导出到txt文件 + TxtUtil.exportDataToTxt(); + break; + case 3://返回主菜单 + return; + } + } + } +} diff --git a/src/main/java/cn/czyx007/week11/controller/GoodMaintenanceMenu.java b/src/main/java/cn/czyx007/week11/controller/GoodMaintenanceMenu.java new file mode 100644 index 0000000..93f5c2b --- /dev/null +++ b/src/main/java/cn/czyx007/week11/controller/GoodMaintenanceMenu.java @@ -0,0 +1,95 @@ +package cn.czyx007.week11.controller; + +import cn.czyx007.week11.bean.Product; +import cn.czyx007.week11.bean.User; +import cn.czyx007.week11.dao.impl.ProductDAOImpl; +import cn.czyx007.week11.utils.ExcelUtil; +import cn.czyx007.week11.utils.MenuUtil; +import cn.czyx007.week11.utils.ProductUtil; +import cn.czyx007.week11.utils.TxtUtil; + +import java.io.IOException; +import java.util.List; +import java.util.Scanner; + +/** + * 商品维护菜单 + * @author : 张宇轩 + * @createTime : 2022/11/10 - 19:53 + */ +public class GoodMaintenanceMenu { + public static void goodMaintenanceMenu(User user) { + if ("管理员".equals(user.getRole())) { + while (true) { + int opt; + System.out.print("===超市商品管理维护====\n" + + "1、从 excel 中导入数据\n" + + "2、从文本文件导入数据\n" + + "3、键盘输入\n" + + "4、商品查询\n" + + "5、返回主菜单\n" + + "请选择(1-5):"); + do { + opt = MenuUtil.checkInput(1, 5); + } while (opt == -1); + + switch (opt) { + case 1://从excel中导入数据 + ExcelUtil.loadDataFromExcel(); + break; + case 2://从文本文件导入数据 + TxtUtil.loadDataFromTxt(); + break; + case 3://键盘输入数据 + ProductUtil.loadDataFromKeyboard(); + break; + case 4://商品查询 + productQuery(); + break; + case 5://返回主菜单 + return; + } + } + } else { + System.out.println("当前用户没有执行该项功能的权限"); + try { + System.out.print("按任意键返回主菜单"); + System.in.read(); + } catch (IOException e) { + e.printStackTrace(); + } + } + } + + /** + * 商品查询 + * 根据输入的商品名称进行模糊查询 + */ + public static void productQuery(){ + Scanner scanner = new Scanner(System.in); + System.out.println("请输入查询的商品名称:"); + String productName = scanner.nextLine(); + + List products = new ProductDAOImpl().selectByProductName(productName); + if (products.size() > 0) { + System.out.printf("满足条件的记录总共%d条,信息如下:\n", products.size()); + System.out.println("序号 条形码 商品名称 单价\t供应商"); + System.out.println("=== ===== ======= \t====\t====="); + + for (int i = 0; i < products.size(); i++) { + System.out.print((i + 1) + "\t" + products.get(i).getBarCode() + "\t" + products.get(i).getProductName() + "\t"); + System.out.printf("%- 8.2f\t", products.get(i).getPrice()); + System.out.println(products.get(i).getSupply()); + } + } else { + System.out.println("不存在满足条件的记录!"); + } + + try { + System.out.print("按任意键返回主菜单"); + System.in.read(); + } catch (IOException e) { + e.printStackTrace(); + } + } +} diff --git a/src/main/java/cn/czyx007/week11/controller/MainMenu.java b/src/main/java/cn/czyx007/week11/controller/MainMenu.java new file mode 100644 index 0000000..a2e1382 --- /dev/null +++ b/src/main/java/cn/czyx007/week11/controller/MainMenu.java @@ -0,0 +1,174 @@ +package cn.czyx007.week11.controller; + +import cn.czyx007.week11.bean.Product; +import cn.czyx007.week11.bean.SaleDetail; +import cn.czyx007.week11.bean.User; +import cn.czyx007.week11.dao.SaleDetailDAO; +import cn.czyx007.week11.dao.impl.ProductDAOImpl; +import cn.czyx007.week11.dao.impl.SaleDetailDAOImpl; +import cn.czyx007.week11.proxy.TransactionProxyFactory; +import cn.czyx007.week11.service.SaleDetailService; +import cn.czyx007.week11.service.UserService; +import cn.czyx007.week11.service.impl.SaleDetailServiceImpl; +import cn.czyx007.week11.service.impl.UserServiceImpl; +import cn.czyx007.week11.utils.MenuUtil; +import cn.czyx007.week11.utils.ProductUtil; + +import java.io.IOException; +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.List; +import java.util.Scanner; + +/** + * 主菜单 + * @author : 张宇轩 + * @createTime : 2022/11/10 + */ +public class MainMenu { + private static User user = null; + + public static void mainMenu(User user) { + MainMenu.user = user; + UserService userService = (UserService) new TransactionProxyFactory(new UserServiceImpl()).getProxy(); + + Scanner scanner = new Scanner(System.in); + int opt; + while (true) { + System.out.printf("\n===超市收银系统=== \n" + + "1、收银\n" + + "2、查询统计\n" + + "3、商品维护\n" + + "4、修改密码\n" + + "5、数据导出\n" + + "6、退出\n" + + "当前收银员:" + user.getChrName() + "\n请选择(1-6):"); + do { + opt = MenuUtil.checkInput(1, 6); + } while (opt == -1); + + switch (opt) { + case 1://1、收银 + cashier(); + break; + case 2://2、查询统计 + querySaleDetailsBySaleTime(); + break; + case 3://3、商品维护 + GoodMaintenanceMenu.goodMaintenanceMenu(user); + break; + case 4://4、修改密码 + userService.changePassword(user.getUsername()); + break; + case 5://5、数据导出 + DataExportMenu.dataExportMenu(); + break; + case 6://6、退出 + System.out.println("您确认退出系统吗(y/n)"); + String exitOpt = scanner.nextLine(); + if ("y".equalsIgnoreCase(exitOpt)) { + System.out.println("欢迎下次继续使用"); + System.exit(0); + } else { + break; + } + } + } + } + + /** + * 功能1:收银 + */ + public static void cashier() { + Scanner scanner = new Scanner(System.in); + ProductDAOImpl productDAO = new ProductDAOImpl(); + + System.out.println("请输入商品条形码(6 位数字字符):"); + String barCode; + while (true) { + barCode = scanner.nextLine(); + if (ProductUtil.checkBarCodeFormat(barCode)) { + if (productDAO.checkBarCodeExist(barCode)) { + System.out.println("请输入商品数量:"); + try { + int count = Integer.parseInt(scanner.nextLine()); + + //生成流水号 + String todayDateStr = new SimpleDateFormat("yyyyMMdd").format(System.currentTimeMillis()); + String lastNo = new SaleDetailDAOImpl().getLastNo(todayDateStr); + String lsh = todayDateStr + lastNo; + + Product product = productDAO.selectByBarCode(barCode); + SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); + SaleDetailService saleDetailService = (SaleDetailService) new TransactionProxyFactory(new SaleDetailServiceImpl()).getProxy(); + + boolean addSuccess = saleDetailService.addSaleDetail(new SaleDetail(lsh, barCode, product.getProductName(), + product.getPrice(), count, user.getUsername(), sdf.parse(sdf.format(System.currentTimeMillis())))); + if (addSuccess) { + System.out.println("成功添加一笔销售数据"); + } else { + System.out.println("添加失败!"); + } + } catch (Exception e) { + System.out.println("添加失败!"); + } + break; + } else { + System.out.println("您输入的商品条形码不存在,请确认后重新输入"); + } + } else { + System.out.println("条形码输入格式不正确,请重新输入"); + } + } + + try { + System.out.println("按任意键返回主菜单"); + System.in.read(); + } catch (IOException e) { + e.printStackTrace(); + } + } + + /** + * 功能2:查询统计 + * 查询统计指定日期所有的销售信息 + */ + public static void querySaleDetailsBySaleTime() { + Scanner scanner = new Scanner(System.in); + SaleDetailDAO saleDetailDAO = new SaleDetailDAOImpl(); + System.out.println("请输入销售日期(yyyy-MM-dd):"); + while (true) { + String dateStr = scanner.nextLine(); + try { + new SimpleDateFormat("yyyy-MM-dd").parse(dateStr); + String[] dateDetail = dateStr.split("-"); + + List saleDetails = saleDetailDAO.selectBySaleTime(dateStr); + int productNum = saleDetailDAO.getProductSumBySaleTime(dateStr); + double saleMoney = saleDetailDAO.getSaleMoneyBySaleTime(dateStr); + + System.out.println(dateDetail[0] + " 年 " + dateDetail[1] + " 月 " + dateDetail[2] + " 日销售如下"); + System.out.println("\t流水号\t\t商品名称\t\t 单价\t数量\t\t金额\t\t\t时间\t\t收银员\n" + + "=============\t=======\t\t======\t====\t========\t===================\t======"); + if (saleDetails.size() != 0) { + for (SaleDetail saleDetail : saleDetails) { + saleDetail.showInfo(); + System.out.println(user.getUsername()); + } + } + System.out.println("销售总数:" + saleDetails.size() + " 商品总件:" + productNum + " 销售总金额:" + saleMoney); + System.out.println("日期:" + dateDetail[0] + " 年 " + dateDetail[1] + " 月 " + dateDetail[2] + " 日"); + break; + } catch (ParseException e) { + System.out.println("你输入的日期格式不正确,请重新输入"); + } + } + + try { + System.out.print("按任意键返回主菜单"); + System.in.read(); + } catch (IOException e){ + e.printStackTrace(); + } + } +} diff --git a/src/main/java/cn/czyx007/week11/dao/ProductDAO.java b/src/main/java/cn/czyx007/week11/dao/ProductDAO.java new file mode 100644 index 0000000..c15a534 --- /dev/null +++ b/src/main/java/cn/czyx007/week11/dao/ProductDAO.java @@ -0,0 +1,39 @@ +package cn.czyx007.week11.dao; + +import cn.czyx007.week11.bean.Product; + +import java.util.List; + +/** + * @author : 张宇轩 + * @createTime : 2022/11/10 + */ +public interface ProductDAO { + /** + * 插入一条商品数据 + * @param product 待插入的商品Product对象 + * @return 影响行数(1为插入成功,0为插入失败) + */ + int insert(Product product); + + /** + * 检验条形码是否已存在 + * @param barCode 待检验重复的条形码 + * @return true:已存在 false:不存在 + */ + boolean checkBarCodeExist(String barCode); + + /** + * 根据条形码获取商品信息 + * @param barCode 条形码 + * @return 条形码为barCode的商品Product对象 + */ + Product selectByBarCode(String barCode); + + /** + * 根据商品名称进行模糊查询,获取所有匹配的商品信息 + * @param productName 商品名称 + * @return 所有匹配的商品信息List集合 + */ + List selectByProductName(String productName); +} diff --git a/src/main/java/cn/czyx007/week11/dao/SaleDetailDAO.java b/src/main/java/cn/czyx007/week11/dao/SaleDetailDAO.java new file mode 100644 index 0000000..b221ea4 --- /dev/null +++ b/src/main/java/cn/czyx007/week11/dao/SaleDetailDAO.java @@ -0,0 +1,52 @@ +package cn.czyx007.week11.dao; + +import cn.czyx007.week11.bean.SaleDetail; + +import java.util.List; + +/** + * @author : 张宇轩 + * @createTime : 2022/11/10 + */ +public interface SaleDetailDAO { + /** + * 插入一条销售明细信息 + * @param saleDetail 一条销售明细信息 + * @return 影响行数(1为插入成功,0为插入失败) + */ + int insert(SaleDetail saleDetail); + + /** + * 获取某一天最后一笔销售明细的流水号 + * @param dateStr 指定日期(yyyyMMdd) + * @return 指定日期最后一笔销售明细的流水号(若该天不存在销售明细则返回"0001") + */ + String getLastNo(String dateStr); + + /** + * 获取某一天商品销售总件数 + * @param dateStr 指定日期(yyyy-MM-dd) + * @return 指定日期的商品销售总件数 + */ + int getProductSumBySaleTime(String dateStr); + + /** + * 获取某一天商品销售总金额 + * @param dateStr 指定日期(yyyy-MM-dd) + * @return 指定日期的商品销售总金额 + */ + double getSaleMoneyBySaleTime(String dateStr); + + /** + * 根据销售日期获取所有销售明细记录 + * @param dateStr 指定日期(yyyy-MM-dd) + * @return 指定日期的所有销售明细记录 + */ + List selectBySaleTime(String dateStr); + + /** + * 获取所有销售明细记录 + * @return 所有销售明细记录 + */ + List selectAll(); +} diff --git a/src/main/java/cn/czyx007/week11/dao/UserDAO.java b/src/main/java/cn/czyx007/week11/dao/UserDAO.java new file mode 100644 index 0000000..304d531 --- /dev/null +++ b/src/main/java/cn/czyx007/week11/dao/UserDAO.java @@ -0,0 +1,32 @@ +package cn.czyx007.week11.dao; + +import cn.czyx007.week11.bean.User; + +/** + * @author : 张宇轩 + * @createTime : 2022/11/10 + */ +public interface UserDAO { + /** + * 修改用户密码 + * @param username 用户登录名 + * @param password 新密码 + * @return 影响行数(1为修改成功,0为修改失败) + */ + int updatePasswordByUsername(String username, String password); + + /** + * 验证密码是否正确 + * @param username 用户名 + * @param password 密码 + * @return 密码正确返回true,密码错误或用户不存在返回false + */ + boolean checkPassword(String username, String password); + + /** + * 根据用户登录名获取用户User对象 + * @param username 用户登录名 + * @return 用户User对象 + */ + User selectByUsername(String username); +} diff --git a/src/main/java/cn/czyx007/week11/dao/impl/ProductDAOImpl.java b/src/main/java/cn/czyx007/week11/dao/impl/ProductDAOImpl.java new file mode 100644 index 0000000..af3fa19 --- /dev/null +++ b/src/main/java/cn/czyx007/week11/dao/impl/ProductDAOImpl.java @@ -0,0 +1,111 @@ +package cn.czyx007.week11.dao.impl; + +import cn.czyx007.week11.bean.Product; +import cn.czyx007.week11.dao.ProductDAO; +import cn.czyx007.week11.utils.DBUtil; + +import java.sql.Connection; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.util.ArrayList; +import java.util.List; + +/** + * @author : 张宇轩 + * @createTime : 2022/11/10 + */ +public class ProductDAOImpl implements ProductDAO { + @Override + public int insert(Product product) { + PreparedStatement ps = null; + int count = 0; + try { + Connection connection = DBUtil.getConnection(); + String sql = "insert into tproduct values(?,?,?,?)"; + ps = connection.prepareStatement(sql); + ps.setObject(1, product.getBarCode()); + ps.setObject(2, product.getProductName()); + ps.setObject(3, product.getPrice()); + ps.setObject(4, product.getSupply()); + count = ps.executeUpdate(); + } catch (Exception e){ + e.printStackTrace(); + } finally { + DBUtil.close(null, ps, null); + } + return count; + } + + @Override + public boolean checkBarCodeExist(String barCode) { + PreparedStatement ps = null; + ResultSet rs = null; + int count = 0; + try { + Connection connection = DBUtil.getConnection(); + String sql = "select count(*) from tproduct where bar_code = ?"; + ps = connection.prepareStatement(sql); + ps.setObject(1, barCode); + rs = ps.executeQuery(); + if(rs.next()){ + count = rs.getInt(1); + } + } catch (Exception e){ + e.printStackTrace(); + } finally { + DBUtil.close(null, ps, rs); + } + return count==1; + } + + @Override + public Product selectByBarCode(String barCode) { + PreparedStatement ps = null; + ResultSet rs = null; + Product product = null; + try { + Connection connection = DBUtil.getConnection(); + String sql = "select * from tproduct where bar_code = ?"; + ps = connection.prepareStatement(sql); + ps.setObject(1, barCode); + rs = ps.executeQuery(); + if(rs.next()){ + String productName = rs.getString("product_name"); + double price = rs.getDouble("price"); + String supply = rs.getString("supply"); + product = new Product(barCode, productName, price, supply); + } + } catch (Exception e){ + e.printStackTrace(); + } finally { + DBUtil.close(null, ps, rs); + } + return product; + } + + @Override + public List selectByProductName(String productName) { + PreparedStatement ps = null; + ResultSet rs = null; + List products = new ArrayList<>(); + try { + Connection connection = DBUtil.getConnection(); + String sql = "select * from tproduct where product_name like ?"; + ps = connection.prepareStatement(sql); + ps.setObject(1, "%" + productName + "%"); + rs = ps.executeQuery(); + while (rs.next()){ + String barCode = rs.getString("bar_code"); + productName = rs.getString("product_name"); + double price = rs.getDouble("price"); + String supply = rs.getString("supply"); + products.add(new Product(barCode, productName, price, supply)); + } + } catch (Exception e){ + e.printStackTrace(); + } finally { + DBUtil.close(null, ps, rs); + } + return products; + } +} diff --git a/src/main/java/cn/czyx007/week11/dao/impl/SaleDetailDAOImpl.java b/src/main/java/cn/czyx007/week11/dao/impl/SaleDetailDAOImpl.java new file mode 100644 index 0000000..77896b9 --- /dev/null +++ b/src/main/java/cn/czyx007/week11/dao/impl/SaleDetailDAOImpl.java @@ -0,0 +1,166 @@ +package cn.czyx007.week11.dao.impl; + +import cn.czyx007.week11.bean.SaleDetail; +import cn.czyx007.week11.dao.SaleDetailDAO; +import cn.czyx007.week11.utils.DBUtil; + +import java.sql.Connection; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.util.ArrayList; +import java.util.Date; +import java.util.List; + +/** + * @author : 张宇轩 + * @createTime : 2022/11/10 + */ +public class SaleDetailDAOImpl implements SaleDetailDAO { + @Override + public int insert(SaleDetail saleDetail) { + PreparedStatement ps = null; + int count = 0; + try { + Connection connection = DBUtil.getConnection(); + String sql = "insert into tsaledetail values(?,?,?,?,?,?,?)"; + ps = connection.prepareStatement(sql); + ps.setObject(1, saleDetail.getLsh()); + ps.setObject(2, saleDetail.getBarCode()); + ps.setObject(3, saleDetail.getProductName()); + ps.setObject(4, saleDetail.getPrice()); + ps.setObject(5, saleDetail.getCount()); + ps.setObject(6, saleDetail.getOperator()); + ps.setObject(7, saleDetail.getSaleTime()); + count = ps.executeUpdate(); + } catch (Exception e){ + e.printStackTrace(); + } finally { + DBUtil.close(null, ps, null); + } + return count; + } + + @Override + public String getLastNo(String dateStr) { + PreparedStatement ps = null; + ResultSet rs = null; + String lastLsh = null; + try { + Connection connection = DBUtil.getConnection(); + String sql = "select max(right(lsh,4)) as lastNo from tsaledetail where left(lsh,8) = ?"; + ps = connection.prepareStatement(sql); + ps.setObject(1, dateStr); + rs = ps.executeQuery(); + if(rs.next()){ + lastLsh = rs.getString("lastNo"); + lastLsh = String.format("%04d", Integer.parseInt(lastLsh)+1); + } + } catch (Exception e){ + e.printStackTrace(); + } finally { + DBUtil.close(null, ps, rs); + } + return lastLsh == null ? "0001" : lastLsh; + } + + @Override + public int getProductSumBySaleTime(String dateStr) { + PreparedStatement ps = null; + ResultSet rs = null; + int productSum = 0; + try { + Connection connection = DBUtil.getConnection(); + String sql = "select sum(count) from tsaledetail where STR_TO_DATE(sale_time,'%Y-%m-%d') = ?"; + ps = connection.prepareStatement(sql); + ps.setObject(1, dateStr); + rs = ps.executeQuery(); + if (rs.next()){ + productSum = rs.getInt(1); + } + } catch (Exception e){ + e.printStackTrace(); + } finally { + DBUtil.close(null, ps, rs); + } + return productSum; + } + + @Override + public double getSaleMoneyBySaleTime(String dateStr) { + PreparedStatement ps = null; + ResultSet rs = null; + double saleMoney = 0; + try { + Connection connection = DBUtil.getConnection(); + String sql = "select sum(count*price) from tsaledetail where STR_TO_DATE(sale_time,'%Y-%m-%d') = ?"; + ps = connection.prepareStatement(sql); + ps.setObject(1, dateStr); + rs = ps.executeQuery(); + if (rs.next()){ + saleMoney = rs.getDouble(1); + } + } catch (Exception e){ + e.printStackTrace(); + } finally { + DBUtil.close(null, ps, rs); + } + return saleMoney; + } + + @Override + public List selectBySaleTime(String dateStr) { + PreparedStatement ps = null; + ResultSet rs = null; + List saleDetails = new ArrayList<>(); + try { + Connection connection = DBUtil.getConnection(); + String sql = "select * from tsaledetail where STR_TO_DATE(sale_time,'%Y-%m-%d') = ?"; + ps = connection.prepareStatement(sql); + ps.setObject(1, dateStr); + rs = ps.executeQuery(); + while (rs.next()){ + String lsh = rs.getString("lsh"); + String barCode = rs.getString("bar_code"); + String productName = rs.getString("product_name"); + Double price = rs.getDouble("price"); + Integer count = rs.getInt("count"); + String operator = rs.getString("operator"); + Date saleTime = rs.getTimestamp("sale_time"); + saleDetails.add(new SaleDetail(lsh, barCode, productName, price, count, operator, saleTime)); + } + } catch (Exception e){ + e.printStackTrace(); + } finally { + DBUtil.close(null, ps, rs); + } + return saleDetails; + } + + @Override + public List selectAll() { + PreparedStatement ps = null; + ResultSet rs = null; + List saleDetails = new ArrayList<>(); + try { + Connection connection = DBUtil.getConnection(); + String sql = "select * from tsaledetail"; + ps = connection.prepareStatement(sql); + rs = ps.executeQuery(); + while (rs.next()){ + String lsh = rs.getString("lsh"); + String barCode = rs.getString("bar_code"); + String productName = rs.getString("product_name"); + Double price = rs.getDouble("price"); + Integer count = rs.getInt("count"); + String operator = rs.getString("operator"); + Date saleTime = rs.getTimestamp("sale_time"); + saleDetails.add(new SaleDetail(lsh, barCode, productName, price, count, operator, saleTime)); + } + } catch (Exception e){ + e.printStackTrace(); + } finally { + DBUtil.close(null, ps, rs); + } + return saleDetails; + } +} diff --git a/src/main/java/cn/czyx007/week11/dao/impl/UserDAOImpl.java b/src/main/java/cn/czyx007/week11/dao/impl/UserDAOImpl.java new file mode 100644 index 0000000..333c627 --- /dev/null +++ b/src/main/java/cn/czyx007/week11/dao/impl/UserDAOImpl.java @@ -0,0 +1,82 @@ +package cn.czyx007.week11.dao.impl; + +import cn.czyx007.week11.bean.User; +import cn.czyx007.week11.dao.UserDAO; +import cn.czyx007.week11.utils.DBUtil; + +import java.sql.Connection; +import java.sql.PreparedStatement; +import java.sql.ResultSet; + +/** + * @author : 张宇轩 + * @createTime : 2022/11/10 + */ +public class UserDAOImpl implements UserDAO { + @Override + public int updatePasswordByUsername(String username, String password) { + PreparedStatement ps = null; + int count = 0; + try { + Connection connection = DBUtil.getConnection(); + String sql = "update tuser set password = sha1(?) where user_name = ?"; + ps = connection.prepareStatement(sql); + ps.setObject(1, password); + ps.setObject(2, username); + count = ps.executeUpdate(); + } catch (Exception e){ + e.printStackTrace(); + } finally { + DBUtil.close(null, ps, null); + } + return count; + } + + @Override + public boolean checkPassword(String username, String password) { + PreparedStatement ps = null; + ResultSet rs = null; + boolean passwordEqual = false; + try { + Connection connection = DBUtil.getConnection(); + String sql = "select password = sha1(?) from tuser where user_name = ?"; + ps = connection.prepareStatement(sql); + ps.setObject(1, password); + ps.setObject(2, username); + rs = ps.executeQuery(); + if(rs.next()){ + passwordEqual = rs.getBoolean(1); + } + } catch (Exception e){ + e.printStackTrace(); + } finally { + DBUtil.close(null, ps, rs); + } + return passwordEqual; + } + + @Override + public User selectByUsername(String username) { + PreparedStatement ps = null; + ResultSet rs = null; + User user = null; + try { + Connection connection = DBUtil.getConnection(); + String sql = "select * from tuser where user_name = ?"; + ps = connection.prepareStatement(sql); + ps.setObject(1, username); + rs = ps.executeQuery(); + if(rs.next()){ + String password = rs.getString("password"); + String chrName = rs.getString("chr_name"); + String role = rs.getString("role"); + user = new User(username, password, chrName, role); + } + } catch (Exception e){ + e.printStackTrace(); + } finally { + DBUtil.close(null, ps, rs); + } + return user; + } +} diff --git a/src/main/java/cn/czyx007/week11/proxy/TransactionProxyFactory.java b/src/main/java/cn/czyx007/week11/proxy/TransactionProxyFactory.java new file mode 100644 index 0000000..b2370f3 --- /dev/null +++ b/src/main/java/cn/czyx007/week11/proxy/TransactionProxyFactory.java @@ -0,0 +1,50 @@ +package cn.czyx007.week11.proxy; + +import cn.czyx007.week11.utils.DBUtil; + +import java.lang.reflect.InvocationHandler; +import java.lang.reflect.Method; +import java.lang.reflect.Proxy; +import java.sql.Connection; + +/** + * 使用动态代理完成事务控制 + * @author : 张宇轩 + * @createTime : 2022/11/10 + */ +public class TransactionProxyFactory { + private Object target; + + public TransactionProxyFactory(Object target) { + this.target = target; + } + + public Object getProxy(){ + ClassLoader classLoader = this.getClass().getClassLoader(); + Class[] interfaces = target.getClass().getInterfaces(); + InvocationHandler handler = new InvocationHandler(){ + @Override + public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { + Connection connection = null; + Object result = null; + try { + connection = DBUtil.getConnection(); + //关闭自动提交,开启事务 + connection.setAutoCommit(false); + + result = method.invoke(target, args); + + //事务完成,提交事务 + connection.commit(); + } catch (Exception e) { + e.printStackTrace(); + } finally { + //关闭数据库连接,若事务失败会自动回滚 + DBUtil.close(connection, null, null); + } + return result; + } + }; + return Proxy.newProxyInstance(classLoader, interfaces, handler); + } +} diff --git a/src/main/java/cn/czyx007/week11/service/ProductService.java b/src/main/java/cn/czyx007/week11/service/ProductService.java new file mode 100644 index 0000000..44ea521 --- /dev/null +++ b/src/main/java/cn/czyx007/week11/service/ProductService.java @@ -0,0 +1,16 @@ +package cn.czyx007.week11.service; + +import cn.czyx007.week11.bean.Product; + +/** + * @author : 张宇轩 + * @createTime : 2022/11/10 + */ +public interface ProductService { + /** + * 添加一条商品信息记录(使用动态代理完成事务控制) + * @param product 待添加的商品信息 + * @return true:添加成功 false:添加失败 + */ + boolean addProduct(Product product); +} diff --git a/src/main/java/cn/czyx007/week11/service/SaleDetailService.java b/src/main/java/cn/czyx007/week11/service/SaleDetailService.java new file mode 100644 index 0000000..4b3da4d --- /dev/null +++ b/src/main/java/cn/czyx007/week11/service/SaleDetailService.java @@ -0,0 +1,16 @@ +package cn.czyx007.week11.service; + +import cn.czyx007.week11.bean.SaleDetail; + +/** + * @author : 张宇轩 + * @createTime : 2022/11/10 + */ +public interface SaleDetailService { + /** + * 添加一条销售明细记录(使用动态代理完成事务控制) + * @param saleDetail 待添加的销售明细记录 + * @return true:添加成功 false:添加失败 + */ + boolean addSaleDetail(SaleDetail saleDetail); +} diff --git a/src/main/java/cn/czyx007/week11/service/UserService.java b/src/main/java/cn/czyx007/week11/service/UserService.java new file mode 100644 index 0000000..7b4655b --- /dev/null +++ b/src/main/java/cn/czyx007/week11/service/UserService.java @@ -0,0 +1,23 @@ +package cn.czyx007.week11.service; + +import cn.czyx007.week11.bean.User; + +/** + * @author : 张宇轩 + * @createTime : 2022/11/10 + */ +public interface UserService { + /** + * 用户登录(使用动态代理完成事务控制) + * @param username 输入的用户登录名 + * @param password 输入的用户密码 + * @return 内部验证密码后返回User对象,若返回null表示密码错误 + */ + User login(String username, String password); + + /** + * 修改用户密码(使用动态代理完成事务控制) + * @param username 已登录的用户名 + */ + void changePassword(String username); +} diff --git a/src/main/java/cn/czyx007/week11/service/impl/ProductServiceImpl.java b/src/main/java/cn/czyx007/week11/service/impl/ProductServiceImpl.java new file mode 100644 index 0000000..9b56759 --- /dev/null +++ b/src/main/java/cn/czyx007/week11/service/impl/ProductServiceImpl.java @@ -0,0 +1,23 @@ +package cn.czyx007.week11.service.impl; + +import cn.czyx007.week11.bean.Product; +import cn.czyx007.week11.dao.ProductDAO; +import cn.czyx007.week11.dao.impl.ProductDAOImpl; +import cn.czyx007.week11.service.ProductService; + +/** + * @author : 张宇轩 + * @createTime : 2022/11/10 + */ +public class ProductServiceImpl implements ProductService { + private static ProductDAO productDAO = new ProductDAOImpl(); + + @Override + public boolean addProduct(Product product) { + if (!productDAO.checkBarCodeExist(product.getBarCode())) { + productDAO.insert(product); + return true; + } + return false; + } +} diff --git a/src/main/java/cn/czyx007/week11/service/impl/SaleDetailServiceImpl.java b/src/main/java/cn/czyx007/week11/service/impl/SaleDetailServiceImpl.java new file mode 100644 index 0000000..20923aa --- /dev/null +++ b/src/main/java/cn/czyx007/week11/service/impl/SaleDetailServiceImpl.java @@ -0,0 +1,19 @@ +package cn.czyx007.week11.service.impl; + +import cn.czyx007.week11.bean.SaleDetail; +import cn.czyx007.week11.dao.SaleDetailDAO; +import cn.czyx007.week11.dao.impl.SaleDetailDAOImpl; +import cn.czyx007.week11.service.SaleDetailService; + +/** + * @author : 张宇轩 + * @createTime : 2022/11/10 + */ +public class SaleDetailServiceImpl implements SaleDetailService { + private static SaleDetailDAO saleDetailDAO = new SaleDetailDAOImpl(); + + @Override + public boolean addSaleDetail(SaleDetail saleDetail) { + return saleDetailDAO.insert(saleDetail) == 1; + } +} diff --git a/src/main/java/cn/czyx007/week11/service/impl/UserServiceImpl.java b/src/main/java/cn/czyx007/week11/service/impl/UserServiceImpl.java new file mode 100644 index 0000000..9f968ed --- /dev/null +++ b/src/main/java/cn/czyx007/week11/service/impl/UserServiceImpl.java @@ -0,0 +1,75 @@ +package cn.czyx007.week11.service.impl; + +import cn.czyx007.week11.bean.User; +import cn.czyx007.week11.dao.UserDAO; +import cn.czyx007.week11.dao.impl.UserDAOImpl; +import cn.czyx007.week11.service.UserService; +import cn.czyx007.week11.utils.PasswordUtil; + +import java.io.IOException; +import java.util.Scanner; + +/** + * @author : 张宇轩 + * @createTime : 2022/11/10 + */ +public class UserServiceImpl implements UserService { + private static UserDAO userDAO = new UserDAOImpl(); + + @Override + public User login(String username, String password) { + User user = null; + if (userDAO.checkPassword(username, password)) { + user = userDAO.selectByUsername(username); + } + return user; + } + + @Override + public void changePassword(String username) { + Scanner scanner = new Scanner(System.in); + + while (true) { + System.out.println("请输入当前用户的原密码:"); + if (!userDAO.checkPassword(username, scanner.nextLine())) { + System.out.println("原密码输入不正确,请重新输入"); + } else { + break; + } + } + + String newPassword; + System.out.println("请设置新的密码:"); + while (true) { + newPassword = scanner.nextLine(); + if (PasswordUtil.checkSecurity(newPassword)) { + break; + } else { + System.out.println(PasswordUtil.PASSWORD_SECURITY_ERROR); + } + } + + String ensurePassword; + System.out.println("请设置新的密码:"); + while (true) { + ensurePassword = scanner.nextLine(); + if (newPassword.equals(ensurePassword)) { + if (userDAO.updatePasswordByUsername(username, newPassword) == 1) { + System.out.println("您已成功修改密码,请谨记"); + } else { + System.out.println("密码修改失败!"); + } + break; + } else { + System.out.println("两次输入的密码必须一致,请重新输入确认密码:"); + } + } + + try { + System.out.print("按任意键返回主菜单"); + System.in.read(); + } catch (IOException e){ + e.printStackTrace(); + } + } +} diff --git a/src/main/java/cn/czyx007/week11/utils/DBUtil.java b/src/main/java/cn/czyx007/week11/utils/DBUtil.java new file mode 100644 index 0000000..c523050 --- /dev/null +++ b/src/main/java/cn/czyx007/week11/utils/DBUtil.java @@ -0,0 +1,78 @@ +package cn.czyx007.week11.utils; + +import java.sql.*; +import java.util.ResourceBundle; + +/** + * 数据库连接工具类 + * @author : 张宇轩 + * @createTime : 2022/11/10 + */ +public class DBUtil { + //静态方法工具类,封闭构造函数 + private DBUtil(){} + + //每个线程向其中绑定自己的数据(数据库连接对象) + private static ThreadLocal local = new ThreadLocal<>(); + + private static ResourceBundle bundle = ResourceBundle.getBundle("jdbc"); + private static String driver = bundle.getString("driver"); + private static String url = bundle.getString("url"); + private static String username = bundle.getString("username"); + private static String password = bundle.getString("password"); + + //类加载时注册驱动 + static { + try { + Class.forName(driver); + } catch (ClassNotFoundException e) { + e.printStackTrace(); + } + } + + /** + * 获取某线程对应的连接对象 + * @return 数据库连接对象connection + * @throws SQLException + */ + public static Connection getConnection() throws SQLException { + Connection connection = local.get(); + if(connection == null){ + //某线程不存在对应的数据库连接对象,创建并绑定到ThreadLocal中 + connection = DriverManager.getConnection(url, username, password); + local.set(connection); + } + return connection; + } + + /** + * 关闭数据库资源 + * @param connection 待关闭的Connection数据库连接对象(关闭后会从ThreadLocal中解绑) + * @param ps 待关闭的PreparedStatement预编译语句对象 + * @param rs 待关闭的ResultSet结果集对象 + */ + public static void close(Connection connection, PreparedStatement ps, ResultSet rs){ + if (connection != null) { + try { + connection.close(); + local.remove();//从ThreadLocal中移除某线程对应的连接对象 + } catch (SQLException e) { + e.printStackTrace(); + } + } + if (ps != null) { + try { + ps.close(); + } catch (SQLException e) { + e.printStackTrace(); + } + } + if (rs != null) { + try { + rs.close(); + } catch (SQLException e) { + e.printStackTrace(); + } + } + } +} diff --git a/src/main/java/cn/czyx007/week11/utils/ExcelUtil.java b/src/main/java/cn/czyx007/week11/utils/ExcelUtil.java new file mode 100644 index 0000000..a22e481 --- /dev/null +++ b/src/main/java/cn/czyx007/week11/utils/ExcelUtil.java @@ -0,0 +1,123 @@ +package cn.czyx007.week11.utils; + +import cn.czyx007.week11.bean.Product; +import cn.czyx007.week11.bean.SaleDetail; +import cn.czyx007.week11.dao.impl.ProductDAOImpl; +import cn.czyx007.week11.dao.impl.SaleDetailDAOImpl; +import cn.czyx007.week11.proxy.TransactionProxyFactory; +import cn.czyx007.week11.service.ProductService; +import cn.czyx007.week11.service.impl.ProductServiceImpl; +import jxl.Sheet; +import jxl.Workbook; +import jxl.write.*; +import jxl.write.Number; + +import java.io.File; +import java.text.SimpleDateFormat; +import java.time.LocalDate; +import java.util.ArrayList; +import java.util.List; + +/** + * @author : 张宇轩 + * @createTime : 2022/11/10 + */ +public class ExcelUtil { + //静态方法工具类,封闭构造函数 + private ExcelUtil(){} + + /** + * 导出数据到excel + */ + public static void exportDataToExcel(){ + String[] dateDetail = LocalDate.now().toString().split("-"); + String exportExcelName = "saleDetail" + dateDetail[0].concat(dateDetail[1]).concat(dateDetail[2]) + ".xls"; + WritableWorkbook wwb = null; + try { + wwb = Workbook.createWorkbook(new File("src/main/resources/" + exportExcelName)); + WritableSheet ws = wwb.createSheet("销售明细表", 0); + + //添加标题 + ws.addCell(new Label(0,0,"lsh")); + ws.addCell(new Label(1,0,"bar_code")); + ws.addCell(new Label(2,0,"product_name")); + ws.addCell(new Label(3,0,"price")); + ws.addCell(new Label(4,0,"count")); + ws.addCell(new Label(5,0,"operator")); + ws.addCell(new Label(6,0,"sale_time")); + + //按序添加每条商品信息 + List saleDetails = new SaleDetailDAOImpl().selectAll(); + SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); + for (int i = 0; i < saleDetails.size(); i++) { + SaleDetail saleDetail = saleDetails.get(i); + ws.addCell(new Label(0,i+1,saleDetail.getLsh())); + ws.addCell(new Label(1,i+1,saleDetail.getBarCode())); + ws.addCell(new Label(2,i+1,saleDetail.getProductName())); + ws.addCell(new Number(3,i+1,saleDetail.getPrice())); + ws.addCell(new Number(4,i+1,saleDetail.getCount())); + ws.addCell(new Label(5,i+1,saleDetail.getOperator())); + ws.addCell(new Label(6,i+1,sdf.format(saleDetail.getSaleTime()))); + } + wwb.write(); + System.out.println("成功导出 " + saleDetails.size() + " 条销售数据到 excel 文件中"); + System.out.print("按任意键返回主菜单"); + System.in.read(); + } catch (Exception e) { + System.out.println("数据导出失败!"); + }finally { + if (wwb != null){ + try { + wwb.close(); + }catch (Exception e){ + e.printStackTrace(); + } + } + } + } + + /** + * 从excel导入数据 + */ + public static void loadDataFromExcel() { + Workbook workbook = null; + try { + workbook = Workbook.getWorkbook(new File("src/main/resources/product.xls")); + Sheet sheet = workbook.getSheet(0); + + ArrayList products = new ArrayList<>(); + int rows = sheet.getRows(); + for (int i = 1; i < rows; i++) { + String barCode = sheet.getCell(0, i).getContents(); + String productName = sheet.getCell(1, i).getContents(); + double price = Double.parseDouble(sheet.getCell(2, i).getContents()); + String supply = sheet.getCell(3, i).getContents(); + + products.add(new Product(barCode, productName, price, supply)); + } + + int cnt = 0; + ProductDAOImpl productDAO = new ProductDAOImpl(); + ProductService productService = (ProductService) new TransactionProxyFactory(new ProductServiceImpl()).getProxy(); + for (Product product : products) { + if (!productDAO.checkBarCodeExist(product.getBarCode())) { + productService.addProduct(product); + cnt++; + } + } + System.out.println("成功从 excel 文件导入 " + cnt + " 条商品数据"); + System.out.print("按任意键返回主菜单"); + System.in.read(); + } catch (Exception e) { + System.out.println("数据导入失败!"); + }finally { + if (workbook != null){ + try { + workbook.close(); + }catch (Exception e){ + e.printStackTrace(); + } + } + } + } +} diff --git a/src/main/java/cn/czyx007/week11/utils/MenuUtil.java b/src/main/java/cn/czyx007/week11/utils/MenuUtil.java new file mode 100644 index 0000000..e5001be --- /dev/null +++ b/src/main/java/cn/czyx007/week11/utils/MenuUtil.java @@ -0,0 +1,33 @@ +package cn.czyx007.week11.utils; + +import java.util.Scanner; + +/** + * @author : 张宇轩 + * @createTime : 2022/11/10 + */ +public class MenuUtil { + //静态方法工具类,封闭构造函数 + private MenuUtil(){} + + /** + * 检查菜单选项输入合法性 + * @param low 选项下界 + * @param high 选项上界 + * @return 合法选项值(不为 - 1) + */ + public static int checkInput(int low, int high) { + Scanner scanner = new Scanner(System.in); + if (scanner.hasNextInt()) { + int opt = scanner.nextInt(); + if (opt >= low && opt <= high) { + return opt; + } + System.out.println("输入无效,只能输入" + low + "-" + high + "的数字"); + } else { + System.out.println("输入无效,只能输入" + low + "-" + high + "的数字\n请重新输入:"); + scanner.next(); + } + return -1; + } +} diff --git a/src/main/java/cn/czyx007/week11/utils/PasswordUtil.java b/src/main/java/cn/czyx007/week11/utils/PasswordUtil.java new file mode 100644 index 0000000..28c86af --- /dev/null +++ b/src/main/java/cn/czyx007/week11/utils/PasswordUtil.java @@ -0,0 +1,36 @@ +package cn.czyx007.week11.utils; + +/** + * @author : 张宇轩 + * @createTime : 2022/11/10 + */ +public class PasswordUtil { + //静态方法工具类,封闭构造函数 + private PasswordUtil(){} + + /** + * 密码不符合复杂性要求 + */ + public static final String PASSWORD_SECURITY_ERROR = "您的密码不符合复杂性要求(密码长度不少于 6 个字符,至少有一个小写字母,至少有一个大写字母,至少一个数字),请重新输入:"; + + /** + * 检验密码复杂性(长度不少于 6 个字符,至少有一个小写字母,至少有一个大写字母,至少一个数字) + * @param password 输入的密码 + * @return true:符合复杂性要求 false:不符合复杂性要求 + */ + public static boolean checkSecurity(String password) { + if (password.length() >= 6) { + int numCnt = 0, lowCnt = 0, upCnt = 0; + for (int i = 0; i < password.length(); i++) { + if (password.charAt(i) >= '0' && password.charAt(i) <= '9') + numCnt++; + else if (password.charAt(i) >= 'a' && password.charAt(i) <= 'z') + lowCnt++; + else if (password.charAt(i) >= 'A' && password.charAt(i) <= 'Z') + upCnt++; + } + return numCnt >= 1 && lowCnt >= 1 && upCnt >= 1; + } + return false; + } +} diff --git a/src/main/java/cn/czyx007/week11/utils/ProductUtil.java b/src/main/java/cn/czyx007/week11/utils/ProductUtil.java new file mode 100644 index 0000000..304f6b2 --- /dev/null +++ b/src/main/java/cn/czyx007/week11/utils/ProductUtil.java @@ -0,0 +1,90 @@ +package cn.czyx007.week11.utils; + +import cn.czyx007.week11.bean.Product; +import cn.czyx007.week11.dao.impl.ProductDAOImpl; +import cn.czyx007.week11.proxy.TransactionProxyFactory; +import cn.czyx007.week11.service.ProductService; +import cn.czyx007.week11.service.impl.ProductServiceImpl; + +import java.io.IOException; +import java.util.Scanner; + +/** + * @author : 张宇轩 + * @createTime : 2022/11/10 + */ +public class ProductUtil { + //静态方法工具类,封闭构造函数 + private ProductUtil(){} + + /** + * 检验条形码格式(6 位数字字符) + * @param barCode 待检验的条形码 + * @return true:格式正确 false:格式错误 + */ + public static boolean checkBarCodeFormat(String barCode) { + if (barCode.length() == 6) { + for (int i = 0; i < 6; i++) { + char each = barCode.charAt(i); + if (!(each >= '0' && each <= '9')) { + return false; + } + } + return true; + } + return false; + } + + /** + * 从键盘录入商品信息 + */ + public static void loadDataFromKeyboard() { + ProductDAOImpl productDAO = new ProductDAOImpl(); + ProductService productService = (ProductService) new TransactionProxyFactory(new ProductServiceImpl()).getProxy(); + + Scanner scanner = new Scanner(System.in); + while (true) { + System.out.println("请输入待录入的商品信息(格式为:商品条形码,商品名称,单价,供应商):"); + String input = scanner.nextLine(); + String[] product = input.split("[,,]"); + + if (product.length != 4) { + System.out.println("输入的数据格式不正确,请重新输入"); + continue; + } + if (!checkBarCodeFormat(product[0])) { + System.out.println("条形码输入格式不正确,请重新输入"); + continue; + } + if (productDAO.checkBarCodeExist(product[0])) { + System.out.println("条形码不能重复,请重新输入"); + continue; + } + + double price; + try { + price = Double.parseDouble(product[2]); + } catch (NumberFormatException e) { + System.out.println("输入的价格格式不正确"); + continue; + } + + if (productService.addProduct(new Product(product[0], product[1], price, product[3]))) { + System.out.println("添加成功"); + } else { + System.out.println("添加失败"); + } + + System.out.println("是否继续录入?(y/n):"); + String opt = scanner.nextLine(); + if ("n".equalsIgnoreCase(opt)) break; + } + + try { + System.out.print("按任意键返回主菜单"); + System.in.read(); + } catch (IOException e){ + e.printStackTrace(); + } + } +} diff --git a/src/main/java/cn/czyx007/week11/utils/TxtUtil.java b/src/main/java/cn/czyx007/week11/utils/TxtUtil.java new file mode 100644 index 0000000..3ba844b --- /dev/null +++ b/src/main/java/cn/czyx007/week11/utils/TxtUtil.java @@ -0,0 +1,84 @@ +package cn.czyx007.week11.utils; + +import cn.czyx007.week11.bean.Product; +import cn.czyx007.week11.bean.SaleDetail; +import cn.czyx007.week11.dao.impl.ProductDAOImpl; +import cn.czyx007.week11.dao.impl.SaleDetailDAOImpl; +import cn.czyx007.week11.proxy.TransactionProxyFactory; +import cn.czyx007.week11.service.ProductService; +import cn.czyx007.week11.service.impl.ProductServiceImpl; + +import java.io.BufferedReader; +import java.io.BufferedWriter; +import java.io.FileReader; +import java.io.FileWriter; +import java.time.LocalDate; +import java.util.ArrayList; +import java.util.List; + +/** + * @author : 张宇轩 + * @createTime : 2022/11/10 + */ +public class TxtUtil { + //静态方法工具类,封闭构造函数 + private TxtUtil(){} + + /** + * 导出数据到txt + */ + public static void exportDataToTxt(){ + String[] dateDetail = LocalDate.now().toString().split("-"); + String exportTextName = "saleDetail" + dateDetail[0].concat(dateDetail[1]).concat(dateDetail[2]) + ".txt"; + try (BufferedWriter bw = new BufferedWriter(new FileWriter("src/main/resources/" + exportTextName))){ + bw.write("lsh bar_code product_name price count operator sale_time\n"); + + List saleDetails = new SaleDetailDAOImpl().selectAll(); + for (SaleDetail saleDetail : saleDetails) { + bw.write(saleDetail.getLsh() + " "); + bw.write(saleDetail.getBarCode() + " "); + bw.write(saleDetail.getProductName() + " "); + bw.write(saleDetail.getPrice() + " "); + bw.write(saleDetail.getCount() + " "); + bw.write(saleDetail.getOperator() + " "); + bw.write(saleDetail.getSaleTime() + "\n"); + } + System.out.println("成功导出 " + saleDetails.size() + " 条销售数据到文本文件中"); + System.out.print("按任意键返回主菜单"); + System.in.read(); + }catch (Exception e){ + e.printStackTrace(); + } + } + + /** + * 从txt文件导入数据 + */ + public static void loadDataFromTxt() { + try (BufferedReader br = new BufferedReader(new FileReader("src/main/resources/product.txt"))) { + List products = new ArrayList<>(); + String line; + + br.readLine(); + while ((line = br.readLine()) != null) { + String[] attributes = line.split(" "); + products.add(new Product(attributes[0], attributes[1], Double.parseDouble(attributes[2]), attributes[3])); + } + + int cnt = 0; + ProductDAOImpl productDAO = new ProductDAOImpl(); + ProductService productService = (ProductService) new TransactionProxyFactory(new ProductServiceImpl()).getProxy(); + for (Product product : products) { + if (!productDAO.checkBarCodeExist(product.getBarCode())) { + productService.addProduct(product); + cnt++; + } + } + System.out.println("成功从文本文件导入 " + cnt + " 条商品数据"); + System.out.print("按任意键返回主菜单"); + System.in.read(); + } catch (Exception e) { + System.out.println("数据导入失败!"); + } + } +} diff --git a/src/main/resources/jdbc.properties b/src/main/resources/jdbc.properties new file mode 100644 index 0000000..bb38a18 --- /dev/null +++ b/src/main/resources/jdbc.properties @@ -0,0 +1,4 @@ +driver=com.mysql.cj.jdbc.Driver +url=jdbc:mysql://localhost:3306/sale?serverTimezone=Asia/Shanghai +username=root +password=123456 \ No newline at end of file diff --git a/src/test/java/cn/czyx007/week11/test/TestUserServiceImpl.java b/src/test/java/cn/czyx007/week11/test/TestUserServiceImpl.java new file mode 100644 index 0000000..3db6392 --- /dev/null +++ b/src/test/java/cn/czyx007/week11/test/TestUserServiceImpl.java @@ -0,0 +1,24 @@ +package cn.czyx007.week11.test; + +import cn.czyx007.week11.proxy.TransactionProxyFactory; +import cn.czyx007.week11.service.UserService; +import cn.czyx007.week11.service.impl.UserServiceImpl; +import org.junit.Test; + +/** + * @author : 张宇轩 + * @createTime : 2022/11/10 - 14:17 + */ +public class TestUserServiceImpl { + @Test + public void testLogin(){ + UserService userService = (UserService) new TransactionProxyFactory(new UserServiceImpl()).getProxy(); + System.out.println(userService.login("abc", "123456")); + } + + @Test + public void testChangePassword(){ + UserService userService = (UserService) new TransactionProxyFactory(new UserServiceImpl()).getProxy(); + userService.changePassword("abc"); + } +}