Java 大作业————使用MySQL的购物车

一、团队介绍

姓名 任务
李天明、康友煌 GUI设计及代码编写
谢晓淞 业务代码编写、MySQL服务器平台部署、git代码库
严威 类和包的结构关系设计以及流程设计、PPT制作

二、项目git地址

码云地址 (数据库用户目前已经删除)

三、项目主要使用技术

  • DAO模式
  • MVC模式
  • MySQL数据库

四、项目其余特点

  • 界面美观
  • 可在不同设备登陆同一账号

五、项目功能架构图与主要功能流程图

六、UML类图

七、项目运行截图

  • 登录界面

  • 登录默认页面(无显示)

  • 商城界面

  • 商品详情界面

  • 购物车界面

  • 订单界面

  • 订单详情界面

八、项目整体流程

数据库

使用的是MySQL数据库,数据库采用的DAO模式,其中订单,商城,购物车,用户账号密码,商家账号密码后台存储结构都是数据库。他们的表结构如下:

用户表(user)

用户表有三个字段,一个是用户id,一个是用户名,另一个是用户密码的md5值

商家表(merchant)

商家表同用户表

订单表(user_order)

订单表这个信息比较多,实际上订单表中都是以单种商品存在的,什么意思呢,当一个订单中有两件商品时,我会将这两件商品分开以相同的订单id存入数据库,这样设计有一个好处,就是商家也可以通过查询这个表当中的merchant_name字段来查询看谁买了自己商品,然后发货。

商城商品表(product)

这个也没什么特别的,只有一点是值得一提的,那就是details字段,我想让不同的商品体现不同的属性,比如买书会有对应的出版社,出版日期,买电脑有cpu信息这一类,我总不能每种都新建一个类来存储,所以我这边是用map来存储的,而map是一个类,要存入数据库就必须序列化,java要序列化好像还要自己写,比较麻烦,所以我干脆直接用来json格式化字符串来保存。

购物车表(cart)

cart表同上其中item_array同样使用的json格式化字符串来存储不确定数量的商品

DAO模式体现

DAO模式是什么,在我看来,DAO模式是用户操作和后端存储结构操作之间的一条铰链。我们先定义好了这样的一个接口:

package model.dao;

import java.util.ArrayList;

import model.order.Order;

public interface OrderDao {
public List<Order> getOrders();
public boolean payOrder(String orderId);
public boolean cancelOrder(String orderId);
public boolean deleteOrder(String orderId);
}

对于GUI的编写人员来说,我只需要知道这样的一个接口就能对后端的存储进行读取,写入,修改等操作,我不需要知道这些操作的具体实现。并且如果后面想要换存储结构,又或者说换一种数据库,比如说MySQL要换成Oracle,那么存储结构的编写人员只要根据这个接口对这些操作进行重写就好了,对GUI的代码不用做太多的改变,就能达到目的,这样将存储结构与其他业务代码分开来,减少了代码的耦合度的模式,就是DAO模式。

MVC模式体现

MVC又是什么,好像学习java总是会学到一些奇怪的缩写。我就拿项目中搜索商品举例吧:

MVC分为Model, View, Controler。其中Controler即为监听器,即上图中的searchButtonActionPerformed,当用户输入完商品关键字,并点击搜索Button时,就会触发这个Controler,Controler从searchTextField,即视图层View,获取到了用户输入,然后Controler转而将得到的用户输入交给了malljdbimpl,即模型层Model,并得到了Model对该关键字的搜索结果,最后再将搜索结果交给了视图层,fillTable方法中的tableModel,进行搜索结果的显示,即视图层更新。

如果上面讲的太复杂听不懂,那么我们可以从以下角度理解这段代码的MVC模式:

假设公司中有一个老板叫监听器(Controler),我们就叫他总监吧,他底下有三个小喽啰,一个是干苦力专门找东西的模范员工老莫(Model),一个是老板的传话秘书S小姐(View1,即上面代码中的asearchTextField),还有一个是负责跟顾客交谈的秘书T小姐(View2,即上述代码中fillTable方法中的tableModel)。这天来了个客户:

S小姐(View1) -> 总监(Controler):“老板有一个客户要找xxx商品。”(传递用户输入)

总监(Controler) -> 老莫(Model):“欸老莫啊,你去找找xxx这个商品的相关资料。”(传递用户输入)

老模玩命翻箱倒柜中......(获得搜索结果)

老莫(Model) -> 总监(Controler):“老板找到了,给你。”(传递搜索结果)

总监(Controler) -> T小姐(View2) :“商品资料找到了,你去跟顾客谈生意吧。”(传递搜索结果)

随后T小姐向顾客展示了搜索结果。(视图更新)

以上,即为我对MVC模式的理解。也是MVC在项目中的体现。附上一张MVC图:

九、项目关键代码

搜索商品

public List<Product> searchProduct(String name, int page) {
List<Product> resultList = new ArrayList<>();
Connection conn = null;
PreparedStatement pstat = null;
ResultSet result ;
// 每页条数
int pieces = 10;
int limitStart = page * pieces - pieces;
int limitEnd = page * pieces - 1;
String sqlValue = "%" + name + "%";
String sql = "select * from product where name like ? or description like ? or brand like ? limit " + limitStart + "," + limitEnd + ";";
String pageSql = "select count(*) from product where name like ? or description like ? or brand like ?;";
try {
conn = Mysql.getConnection();
pstat = conn.prepareStatement(sql);
pstat.setString(1, sqlValue);
pstat.setString(2, sqlValue);
pstat.setString(3,sqlValue);
// 设置参数写入
result = pstat.executeQuery();
while(result.next()) {
String productId = result.getString(1);
String productName = result.getString(2);
String productDescription = result.getString(3);
double productPrice = result.getDouble(4);
String productBrand = result.getString(5);
String merchant_name = result.getString(6);
String detailsString = result.getString(7);
HashMap<String, String> details = jsonToMap(detailsString);
resultList.add(new Product(productId, productName, productDescription, productPrice, productBrand, details,merchant_name));
}
pstat.close();
pstat = conn.prepareStatement(pageSql);
pstat.setString(1, sqlValue);
pstat.setString(2, sqlValue);
pstat.setString(3,sqlValue);
result = pstat.executeQuery();
if (result.next()) {
this.pageNumber = result.getInt(1);
if (this.pageNumber % 10 == 0) {
this.pageNumber /= 10;
}
else {
this.pageNumber = this.pageNumber / 10 + 1;
}
}
} catch (SQLException sqle) {
sqle.printStackTrace();
} catch (Exception e){
e.printStackTrace();
} finally {
Mysql.realeaseAll(null,pstat, conn);
}
System.out.println(resultList.size());
this.products = resultList;
return resultList;
}

生成订单

public boolean generalOrder(CartItemsJDBCImpl cart, String address, long phoneNumber) {
Order newOrder = new Order(
cart.getItems(),
cart.totalPrice(),
cart.userNameGet(),
address,
System.currentTimeMillis(),
phoneNumber,
"unpaid"
);
this.orders.add(newOrder);
Connection conn = null;
PreparedStatement pstat = null;
boolean result = false;
long maxId = 0; String sql = "insert into user_order(order_id, user_name, product_id,product_name, product_description, product_price, product_brand, product_details, merchant_name, amount, address, timetamp, phone_number, order_status) values (?,?,?,?,?,?,?,?,?,?,?,?,?,?);";
String sqlMaxOrderId = "select max(order_id) from user_order;";
try {
conn = Mysql.getConnection();
pstat = conn.prepareStatement(sqlMaxOrderId);
ResultSet idResult = pstat.executeQuery();
if(idResult.next()) {
maxId = idResult.getLong(1);
}
pstat.close();
newOrder.setOrderId(maxId + 1 + "");
// 插入数据库
for(CartItem eItem : newOrder.getItems()) {
System.out.println(eItem.getProduct());
pstat = conn.prepareStatement(sql);
pstat.setLong(1, maxId + 1);
pstat.setString(2, this.userName);
pstat.setString(3, eItem.getProduct().getProductId());
pstat.setString(4, eItem.getProduct().getProductName());
pstat.setString(5, eItem.getProduct().getProductDescription());
pstat.setDouble(6, eItem.getProduct().getProductPrice());
pstat.setString(7, eItem.getProduct().getBrand());
pstat.setString(8, JSONObject.fromObject(eItem.getProduct().getDetails()).toString());
pstat.setString(9, eItem.getProduct().getMerchant_name());
pstat.setInt(10, eItem.getAmount());
pstat.setString(11, newOrder.getAddress());
pstat.setLong(12, newOrder.getTimesTamp());
pstat.setLong(13, phoneNumber);
pstat.setString(14, newOrder.getOrderStatus());
if(pstat.executeUpdate() > -1) {
result = true;
}
else {
result = false;
}
pstat.close();
}
} catch (SQLException sqle) {
sqle.printStackTrace();
} catch (Exception e){
e.printStackTrace();
} finally {
Mysql.realeaseAll(null,pstat, conn);
}
return result;
}

支付订单

public boolean payOrder(String orderId) {
Connection conn = null;
PreparedStatement pstat = null;
int result = -1;
String sql = "update user_order set order_status = ? where user_name = ? and order_id = ? and order_status = 'unpaid';";
try {
conn = Mysql.getConnection();
pstat = conn.prepareStatement(sql);
pstat.setString(1, "paid");
pstat.setString(2, this.userName);
pstat.setString(3, orderId);
result = pstat.executeUpdate();
} catch (SQLException sqle) {
sqle.printStackTrace();
} catch (Exception e){
e.printStackTrace();
} finally {
Mysql.realeaseAll(null,pstat, conn);
}
if(result > 0) {
for(int i = 0; i < this.orders.size(); i++) {
Order e = this.orders.get(i);
if(e.getOrderId().equals(orderId)) {
this.orders.get(i).setOrderStatus("paid");
break;
}
}
}
return result > 0 ? true : false;
}

从购物车中读取订单信息到本地

public void readData() {
Connection conn = null;
PreparedStatement pstat = null;
ResultSet r = null;
String sql = "select item_array from cart where user_name = ?;";
try {
conn = Mysql.getConnection();
pstat = conn.prepareStatement(sql);
pstat.setString(1, this.name);
r = pstat.executeQuery();
// 数据不存在该用户的购物车,使用insert增添一个空的购物车
if(r.next() == false) {
this.items = new ArrayList<>();
sql = "insert into cart(user_name, item_array) values (?,NULL);";
pstat.close();
pstat = conn.prepareStatement(sql);
pstat.setString(1, this.name);
pstat.execute();
}
else {
String text = r.getString(1);
// 数据库中购物车为NULL,为目前对象新建空购物车
if(text == null) {
this.items = new ArrayList<>();
}
else {
JSONArray cartItemJSONArray = JSONArray.fromObject(text);
this.items = (List<CartItem>) (JSONArray.toList(cartItemJSONArray, CartItem.class));
}
}
} catch (SQLException sqle) {
sqle.printStackTrace();
} catch (Exception e){
e.printStackTrace();
} finally {
Mysql.realeaseAll(null,pstat, conn);
}
}

往购物车添加商品并更新到数据库

public boolean addItem(Product other, int num) {
for (CartItem e : this.items) {
// 已存在该商品,则在原本数量的基础上继续添加
if (e.getProduct().getProductId().equals(other.getProductId())) {
return this.changeItemAmount(other.getProductId(), num);
}
}
this.items.add(new CartItem(other, num));
// 连接数据库更新数据
return this.databaseUpdate();
}

用户登录

public boolean login(String name, String password) {
password = getMD5(password);
if(password == "") {
return false;
}
Connection conn = null;
PreparedStatement pstat = null;
ResultSet r = null;
String sql = "select * from user where user = ? and password = ?;";
try {
conn = Mysql.getConnection();
pstat = conn.prepareStatement(sql);
pstat.setString(1, name);
pstat.setString(2, password);
r = pstat.executeQuery();
this.loginStatus = r.next();
} catch (SQLException sqle) {
sqle.printStackTrace();
} catch (Exception e){
e.printStackTrace();
} finally {
Mysql.realeaseAll(null,pstat, conn);
}
if(this.loginStatus == true) {
this.currentUser = name;
this.accountInit();
}
return this.loginStatus;
}

十、尚待改进或未实现的内容

  • GUI的变量命名其实还不太规范
  • 实际上商家的业务代码我也已经写完了,但是GUI部分尚未实现,原本的想法是为商家也设计一个客户端
  • 安全性不好,因为这个程序是在本地运行的,包括数据库连接部分,所以不法分子可以通过反编译class文件得到数据库的账号密码,从而进行不花钱买东西这种情况,又或者数据库污染。

十一、设计过程中使用到的帮助文档

Java MySQL连接

MySQL教程

Java JSON教程

java大作业博客--购物车的更多相关文章

  1. Java第二次博客作业

    Java第二次博客作业 时间过的很快啊,在不知不觉中这门课程的学习也就快要过去一半了,现在就来总结一下在这个第二个月的学习当中存在的问题以及得到的心得. 1.前言 第四次题目集和第五次题目集给我的感觉 ...

  2. Java课程设计——博客作业教学数据分析系统(201521123082 黄华林)

    Java课程设计--博客作业教学数据分析系统(201521123082 黄华林) 一.团队课程设计博客链接 博客作业教学数据分析系统(From:网络五条狗) 二.个人负责模块或任务说明 1.网络爬虫 ...

  3. iOS组件化思路-大神博客研读和思考

    一.大神博客研读 随着应用需求逐步迭代,应用的代码体积将会越来越大,为了更好的管理应用工程,我们开始借助CocoaPods版本管理工具对原有应用工程进行拆分.但是仅仅完成代码拆分还不足以解决业务之间的 ...

  4. Java课程设计博客(个人)

    Java课程设计博客(个人) 1. 团队课程设计博客链接 http://www.cnblogs.com/wkfg/p/7063081.html 2. 个人负责模块或任务说明 负责模块/任务:编写doG ...

  5. < JAVA - 大作业(2)仿qq即时通讯软件 >

    < JAVA - 大作业(2)仿qq即时通讯软件 > 背景 JAVA上机大作业:设计一个仿qq即时通讯软件 任务简要叙述:设计一款仿QQ的个人用户即时通讯软件,能够实现注册,登陆,与好友聊 ...

  6. Java课程设计博客(团队)

    Java课程设计博客(团队) 1. 团队/项目名称 使用JAVA实现简易HTTP服务器 2. 团队成员 组长:林一心 组员:张杭镖 3. 项目git地址 https://github.com/oran ...

  7. Java实现个人博客网站

    说明:该项目是实验楼用户"LOU3165780622"发布在实验楼上的项目教程:[Java实现个人博客],未经允许,禁止转载: 该项目利用 SSM 框架和 Mysql 以及一些简单 ...

  8. JAVA大作业汇总1

    JAVA大作业 代码 ``` package thegreatwork; import javafx.application.; import javafx.scene.control.; impor ...

  9. JAVA大作业汇总2

    JAVA大作业2 代码 package thegreatwork; //Enum一般用来表示一组相同类型的常量,这里用于表示运动方向的枚举型常量,每个方向对象包括方向向量. public enum D ...

随机推荐

  1. Python 下载图片的三种方法

    import os os.makedirs('./image/', exist_ok=True) IMAGE_URL = "http://image.nationalgeographic.c ...

  2. SpringDataRedis简单入门介绍

    1:问题引入 在实际开发中,开发的每一个项目,每天都有大量的人访问,对数据库造成很大的访问压力,甚至是瘫痪.那如何解决呢?我们通常的做法有两种:一种是数据缓存.一种是网页静态化.我们今天讨论第一种解决 ...

  3. Vue devtool插件安装后无法使用,提示“vue.js not detected”的解决方法

    vue devtool下载 极简插件  github vue devtool安装 点击谷歌浏览器箭头所指图标-更多工具-扩展程序   ①:直接将后缀为crx的安装包拖进下图区域即可自动安装     ② ...

  4. css彩虹文字

    用CSS3实现彩虹文字的效果,只在Webkit内核的浏览器(谷歌浏览器或移动端)上有效果. background-image: -webkit-gradient(linear, left top, r ...

  5. Entity Framework 6 中如何获取 EntityTypeConfiguration 的 Edm 信息?(二)

    接着上一篇 直接贴代码了: using System; using System.Collections.Generic; using System.Data.Entity; using System ...

  6. ADO.NET中的5个主要对象

    1.Connection:主要是开启程序和数据库之间的连接.没有利用连接对象将数据库打开,是无法从数据库中取得数据的. Close和Dispose的区别,Close以后还可以Open,Dispose以 ...

  7. Windows Form父子两个窗体之间的传值测试

    1:先看测试的效果图: 2:全部的代码 using System; using System.Windows.Forms; namespace WindowsForms { public partia ...

  8. 剑指 Offer——2. 替换空格

    题目描述 请实现一个函数,将一个字符串中的每个空格替换成"%20".例如,当字符串为We Are Happy.则经过替换之后的字符串为We%20Are%20Happy. 思路与实现 ...

  9. java基本程序设计结构总结

    学习一门语言:(1)掌握它的表现形式(2)这些语言什么应用. 1.1关键字 1.关键字是被赋予了特殊含义的单词. 2.关键字特点:关键字所有字母都小写. 3.类名的每一个单词开头必须大写. 1.2标识 ...

  10. 深入浅出《设计模式》之工厂模式(C++)

    前言 模式介绍 在之前简单工厂模式中,我们介绍了简单工厂模式的缺陷是违背了开放-封闭原则.如果在面馆中添加了烤海参,那将会修改waiter工厂类.违背了类内封闭原则. 还以面馆为例,现在两种面,用一个 ...