java项目------松子铺的收银台

此项目是一个收银的系统,它主要是基于字符界面。

在此项目中我们的目的是实现以下功能:
1.公共端:(1)入口命令 :注册(ZC),登录 (DL)
(2)公共命令:关于系统(GYXT), 帮助信息(BZXX), 退出系统(TCXT)
======================================================
2.管理端:
(1)账户信息:查看账户(CKZH) ,重置密码(CZMM) ,启停账户(QTZH)
(2)商品信息:浏览商品(LLSP),上架商品(SJSP)
下架商品(XJSP),更新商品(GXSP)
(3)公共命令

=======================================================
3.用户端:
(1)商品信息:浏览商品(LLSP)
(2)公共命令
(3)我的订单:查看订单(CKDD),支付订单(ZFDD)

项目的核心技术:
1.MySQL数据库,包含对字段的增删改查和表与表之间的连接等sql语句的编写
2.JDBC编程,采用DataSource方式连接数据库
3.注解,通过注解的方式对命令进行分类
4.Scanner,获取输入输出流
5.Map集合

步骤
这个项目涉及到四张表,首先我们在数据库中将表建立起来:
这四张表分别是:账户表,商品表,订单,订单项。
要完成这个项目,首先我们要知道这些表之间的关系:
如下图所示:
在这里插入图片描述
(1)账户和商品之间:一个账户可以拥有多个商品,商品有很多库存,可以被多个用户所拥有,因此他们是多对多的关系。
(2)账户和订单之间:一个账户可以有多个订单,但是一个订单只属于一个账户,因此他们之间是一对多的关系。
(3)订单和商品之间:一个订单可能包含多个商品,一个商品只能存在于一个订单,因此他们之间是一对多的关系。
(4)订单和订单项之间:订单和订单项是一对多的关系,一张订单可以对应多个订单项。

将四张表建立起来:

Accout(账户):

drop table if exists `account`;
create table if not exists `account`
(
id int primary key auto_increment comment '帐号编号',
username varchar(12) not null comment '帐号',
password varchar(128) not null comment '密码',
name varchar(32) not null comment '姓名',
account_type int default 1 not null comment '帐号类型 1 管理员 2 客户',
account_status int default 1 not null comment '帐号状态 1 启用 2 锁定'
);

Goods(商品):

drop table if exists `goods`;
create table if not exists `goods`
(
id int primary key auto_increment comment '商品编号',
name varchar(128) not null comment '商品名称',
introduce varchar(256) default '暂无' not null comment '商品简介',
stock int not null comment '商品库存',
unit varchar(12) not null comment '库存单位',
price int not null comment '商品价格,单位:分',
discount int default 100 not null comment '商品折扣,[0,100]'
);

Order(订单):

drop table if exists `order`;
create table if not exists `order`
(
id varchar(32) primary key comment '订单编号',
account_id int not null comment '帐号编号',
account_name varchar(12) not null comment '帐号',
create_time datetime not null comment '创建时间',
finish_time datetime default null comment '完成时间',
actual_amount int not null comment '实际金额,单位:分',
total_money int not null comment '总金额,单位:分',
order_status int not null comment '支付状态 1 待支付 2 完成'
);

OrderItem(订单项):

drop table if exists `order_item`;
create table if not exists `order_item`
(
id int primary key auto_increment comment '订单条目编号',
order_id varchar(32) not null comment '订单编号',
goods_id int not null comment '商品编号',
goods_name varchar(128) not null comment '商品名称',
goods_introduce varchar(256) default '暂无' not null comment '商品简介',
goods_num int not null comment '商品数量',
goods_unit varchar(12) not null comment '库存单位',
goods_price int not null comment '商品价格,单位:分',
goods_discount int default 100 not null comment '商品折扣,[0,100]'
);

注意:在建表的过程中一定要将主键标出。
接下来,我们对项目进行分层处理
如下图所示:
在这里插入图片描述
上层依赖于下层,下层不依赖于上层。
DAO:Data Access Object的简称:数据访问对象。
因此我们在DAO层中编写对数据库进行操作的代码。
然后从数据库逐级返回。
因此我们建立如图所示的结构:
在这里插入图片描述
1.在BaseDao中建立数据库的连接,此处我采用了datasource的方法进行连接
之所以采用datasource的方法,而不用DriverManager的原因:
datasource共有三种类型的实现:
(1)基本实现 - 生成标准的 Connection 对象
(2)连接池实现 - 生成自动参与连接池的 Connection 对象。此实现与中间层连接池管理器一起使用。
(3)分布式事务实现 - 生成一个 Connection 对象,该对象可用于分布式事务,大多数情况下总是参与连接池。此实现与中间层事务管理器一起使用,大多数情况下总是与连接池管理器一起使用。

一个DataSource对象代表了一个真正的数据源,当一个DataSource对象注册到名字服务中,应用程序就可以通过名字服务获得DataSource对象,并用它来产生一个与DataSource代表的数据源之间的连接.它无需硬性编码驱动,而DriverManager需要硬性编码驱动。

因为它有连接池的实现,所以,当每次用完connection后,将其放入池子里,当下次使用的时候从池子里拿出来使用,即重复利用,不会有频繁的创建和销毁。

2.在实体类中给我们四个表中的字段提供属性,并得到他们的get和set 方法。
在此引入了@Data注解:
自动为当前类提供getter和setter,toString,equals等方法,未显现,但调用就可拿到。
要引入@Data注解就需要安装lombok插件,这个根据自己的idea版本在官网下载即可。

3.接着就开始实现相应的功能,具体操作各个类。
Command操作Service,Service操作Dao
(1).因为每一个命令都要操作Service层,每次都要重新输入,太繁琐,太麻烦。因此在cmd中建一个接口Command,在接口中写入Scanner对象,通过Scanner来读取输入流的信息。定义一个统一实现一个方法。统一方法所观察的对象:subject对象
(2).因为操作每一个命令都得重启Service层,然后通过服务操作Dao层,太浪费所以我写了一个抽象类Abstract,在Abstract中启动所有的服务
重启服务的同时实现command接口,command接口里又有统一的操作和Scanner。
然后让每一个命令继承这个抽象的接口,都会重新实现自己的excute方法,这个excute()方法是统一的。

Command接口:

public interface Command {
    Scanner scan=new Scanner(System.in);
    void execute(Subject subject);
}

Abstract抽象类的实现:


public abstract class Abstract implements Command  {//实现command接口
    //启动所有的服务
public AccountService accountService;
public GoodsService goodsService;
public OrderService orderService;
public  Abstract(){
    this.accountService=new AccountService();
    this.goodsService=new GoodsService();
    this.orderService=new OrderService();
}
public void printInfo(String info){
    System.out.println(info);
}
}

但是不同的用户登录看到的商品信息不一样,那怎么处理呢,一开始,很容易想到用if-else实现,但是经过尝试后发现if-else的代码量太冗余,因此想到了注解,通过注解来对命令进行分类。
因此,建立了以下四个注解:
在这里插入图片描述

如其中一个注解的代码所示:

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface EntranceCommand {
}

在其中加入了@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE),那么这两句注解是用来干什么的呢?

(1)@Retention(RetentionPolicy.RUNTIME):注解不仅被保存到class文件中,jvm加载class文件之后,仍然存在。
RUNTIME:运行之后,信息就会保存在class中,因为我们最后就是要通过反射去实现,而反射就是拿到class对象等等。
(2)@Target(ElementType.TYPE):
@Target说明了Annotation所修饰的对象范围:用于描述类,接口(包括注解类型)或enum声明。
TYPE:注解修饰到类上

当有了注解之后,在执行命令等操作的时候,我们就可以通过加上注解来对其进行分类。那它是如何分类的呢?
答案就是通过反射,利用反射,将命令分到不同的map集合中。
通过命令进行分类:
在这里插入图片描述
在前面说过dao层是真正操作数据库的,那如何处理dao层呢?
如上面的结构图所示,需要在三个类里操作:
AccountDao GoodsDao OrderDao
这三个类都继承子BaseDao.
在这些类中实现对应的方法
方法中的具体步骤:
1.先拿到连接
2.编写sql语句
3.将Sql语句进行预编译存储到PreparedStatement对象
好处:可以使用此对象多次高效地执行修改语句。适合用于多次执行的sql语句,可以防止SQL注入,预编译好之后,不用再次编译,提高了效率。
4.最终会生成一个ResultSet对象,支持批处理
5.解析resultset,拿到对应的account

===========================================================
难点:
此项目最难解决的问题就是如何处理订单和订单项
在此重点说一下支付订单和浏览订单的实现。
实现支付订单,首先要实现插入订单和插入订单明细:
前面的功能都是让它自动提交事务,在OrderDao中,我将其设置为手动提交事务,当提交失败时,使其回滚。
在此,调用了 addBatch() :把所有的预编译的语句先全部放好,然后调addBatch批量插入。
因为每次支付完订单之后,商品的数量就会减少,因此,在GoodsOrder里提供一个 public boolean updateAfterPay(Goods goods,int goodsNum){}方法,然后在支付订单命令里调用,判断库存是否更新。

因为订单和订单项之间是一对多的关系,因此在实现查询订单信息时,若直接写sql语句有点麻烦且容易出错,因此如下图所示,在resources中处理两个表的连接,在此使用了左连接。
在这里插入图片描述
在经过以上的处理之后,我们就直接写如下语句

  String sql=this.getSql("@query_order_by_account");

然后继续其他步骤即可。
项目功能结果:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
以上就是本项目的实现过程。
在本次项目中,一开始遇到了很多困难,一开始没有想通订单和订单项之间的关系,想通了它们是一对多的关系之后,但是老在建立两表的关系以及sql语句上出错,经过上网查询,发现可以在resources中建立一个query_order_by_account.sql,在它里面处理两表关系。在此次项目中,通过注解来对命令进行分类是一个很大的收获。

完整工程项目源代码请看github链接:
https://github.com/zhdfuture/Program-cashSystem/commit/d912535c4e0113e978af1ad4100fa466769e9b7a

  • 6
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
这是一个基于SSM(Spring + Spring MVC + MyBatis)框架和Vue.js的在线收银系统项目。该项目包含了源代码、部署说明、系统介绍以及数据库设计。以下是关于这个项目的简要介绍:源码:本项目提供了完整的源代码,包括前端Vue.js应用和后端SSM框架。这使得开发者可以轻松地理解和修改代码,以满足自己的需求。部署说明:项目提供了详细的部署说明,指导开发者如何将项目部署到服务器上。部署过程需要配置数据库连接信息、调整服务器环境等。通过阅读部署说明,开发者可以顺利完成项目的部署工作。系统介绍:项目简介部分详细介绍了在线收银系统的功能和特点。该系统支持多种支付方式,如微信支付、支付宝支付等,同时具备商品管理、订单管理、用户管理等功能。此外,系统还具有一定的安全性和稳定性,能够满足企业级的应用需求。数据库设计:项目数据库设计文件详细描述了数据库表结构和关系。这些表包括用户表、商品表、订单表等,用于存储系统的各种数据。通过对数据库的设计,开发者可以更好地理解系统的架构和数据流程。总之,这个基于SSM+Vue的在线收银系统项目为开发者提供了一个完整的解决方案,可以帮助他们快速搭建一个功能丰富、性能稳定的在线收银系统。通过阅读源码、部署说明和数据库设计文件,开发者可以深入了解项目实现细节,从而提高自己的开发能力。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值