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");
+ }
+}