• 极客专栏正式上线!欢迎访问 https://www.jikewenku.com/topic.html
  • 极客专栏正式上线!欢迎访问 https://www.jikewenku.com/topic.html

Javaweb网上商城项目实战(22)提交订单模块

项目实战 Geekerstar 11个月前 (05-27) 644次浏览 已收录 0个评论 扫描二维码
文章目录[隐藏]

分析订单表-以超市小票为例

超市小票案例

会员ID:583381
流水号:jlf_ba_31_sy003_1002
交易时间:2018年3月10日08:41:53
商品名称  商品价格 商品数量  小计
好日子    15       2         30
芙蓉王    25       2         50
黄鹤楼    15       3         45
大前门    10       1         10
总金额:135元

设计表,存储小票上的数据

会员id  流水号  交易时间 商品名称  商品价格 商品数量  小计  总金额
1231231  XXX     XXXX   好日子     15         2        30   135
1231231  XXX     XXXX   芙蓉王     25         2        50   135
1231231  XXX     XXXX   黄鹤楼     15         3        45   135
1231231  XXX     XXXX   大前门     10         1        10   135

这种是我们最直接的想法,直接把订单项存到一个表中,但是这种设计有一个严重的弊端。

弊端:数据冗余严重。
DB原则:存储最少的数据,办更多的事情。

改进方案

一个表专注于交易描述,订单表 orders

订单id(流水号)   会员id    交易时间  总金额   收货人姓名 地址 电话 订单状态(1234)
1123            1231231       XXXX     135
1124            1234444       YYYY     200

orders表中的会员id列参照了用户表uid

订单状态:
买家:下单未付款,付款未发货,已发货,签收
卖家: 未付款,发货,未签收,已收货(结束)

一个表专注于每笔订单详细交易情况,订单项orderitem

订单项id   商品id  数量  小计   所在订单编号
001        p003     2     30     1123
002        p005     2     50     1123
003        p101     3     45     1123
004        p220     1     10     1123
005        p334     1     101    1124
006        p556     3     54     1124
007        p445     5     45     1124

orderitem表中的商品id参照了商品表的pid

orderitem表中的所在订单编号参照了订单表的订单id

我们本次项目所用的就是第二个方案,之前我们已经完成了表的设计

提交订单原理分析

用户点击提交订单,将购物车中的数据以订单/订单项形式保存下来。

保存订单:


为订单表中插入一行数据,描述本次交易,这行数据部分数据是通过程序赋予,部分数据来自购物车的,部分数据来自session中的用户。

oid:UUIDUtils orderTime:new Date(); total: 从购物车获取

state:1 address: null name:null telephone:null uid:从session中的用户获取

保存订单项:

向订单项表中插入数据,描述当前订单的详细的购买信息,部分数据来自于购物车,部分数据需要通过程序赋予。

itemid: UUIDUtils quantity:来自于购物车中的购物项

total:来自于购物车中的购物项 pid:来自于购物车上的购物项下商品对象pid oid:来自于当前订单id

提交订单时,订单以及订单项必须同时成功(事务)

具体实现

实现订单模块相关程序

创建OrderServlet、OrderService、OrderServiceImp、OrderDao、OrderDaoImp。

在domain中创建Order和OrderItem。

Order.java

根据数据库Order表创建

package com.geekerstar.store.domain;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

public class Order {
	@Override
	public String toString() {
		return "Order [oid=" + oid + ", ordertime=" + ordertime + ", total=" + total + ", state=" + state + ", address="
				+ address + ", name=" + name + ", telephone=" + telephone + ", user=" + user + ", list=" + list + "]";
	}

	private String oid; //订单编号
	private Date ordertime; //下单时间
	private double total; //总计
	private int state; //状态
	private String address; //收货人地址
	private String name; //收货人姓名
	private String telephone; //收货人电话

	// private String uid;
	// 1_程序对象和对象发生关系,而不是对象和对象的属性发生关系
	// 2_设计Order目的:让order携带订单上的数据向service,dao传递,user对象是可以携带更多的数据
	private User user;

	// 程序中体现订单对象和订单项之间关系,我们再项目中的部分功能中有类似的需求:查询订单的同时还需要获取订单下所有的订单项
	private List<OrderItem> list = new ArrayList<OrderItem>();

	public String getOid() {
		return oid;
	}

	public void setOid(String oid) {
		this.oid = oid;
	}

	public Date getOrdertime() {
		return ordertime;
	}

	public void setOrdertime(Date ordertime) {
		this.ordertime = ordertime;
	}

	public double getTotal() {
		return total;
	}

	public void setTotal(double total) {
		this.total = total;
	}

	public int getState() {
		return state;
	}

	public void setState(int state) {
		this.state = state;
	}

	public String getAddress() {
		return address;
	}

	public void setAddress(String address) {
		this.address = address;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public String getTelephone() {
		return telephone;
	}

	public void setTelephone(String telephone) {
		this.telephone = telephone;
	}

	public User getUser() {
		return user;
	}

	public void setUser(User user) {
		this.user = user;
	}

	public List<OrderItem> getList() {
		return list;
	}

	public void setList(List<OrderItem> list) {
		this.list = list;
	}

}

OrderItem

根据数据库orderitem表创建

package com.geekerstar.store.domain;

public class OrderItem {
	private String itemid; //id
	private int quantity; //数量
	private double total; //小计
	
	//1_对象对应对象
	//2_product,order携带更多的数据
	private Product product;
	private Order order;
	
	public String getItemid() {
		return itemid;
	}
	public void setItemid(String itemid) {
		this.itemid = itemid;
	}
	public int getQuantity() {
		return quantity;
	}
	public void setQuantity(int quantity) {
		this.quantity = quantity;
	}
	public double getTotal() {
		return total;
	}
	public void setTotal(double total) {
		this.total = total;
	}
	public Product getProduct() {
		return product;
	}
	public void setProduct(Product product) {
		this.product = product;
	}
	public Order getOrder() {
		return order;
	}
	public void setOrder(Order order) {
		this.order = order;
	}
}

JSP页面准备工作

在Cart.jsp中修改提交订单链接到OrderServlet

<a href="${pageContext.request.contextPath}/OrderServlet?method=saveOrder">

OrderServlet中增加saveOrder方法

package com.geekerstar.store.web.servlet;

import java.util.Date;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.geekerstar.store.domain.Cart;
import com.geekerstar.store.domain.CartItem;
import com.geekerstar.store.domain.Order;
import com.geekerstar.store.domain.OrderItem;
import com.geekerstar.store.domain.User;
import com.geekerstar.store.service.OrderService;
import com.geekerstar.store.service.serviceImp.OrderServiceImp;
import com.geekerstar.store.utils.UUIDUtils;
import com.geekerstar.store.web.base.BaseServlet;

public class OrderServlet extends BaseServlet {
	// saveOrder 将购物车中的信息以订单的形式保存
	public String saveOrder(HttpServletRequest req, HttpServletResponse resp) throws Exception {
		// 确认用户登录状态
		User user = (User) req.getSession().getAttribute("loginUser");
		if (null == user) {
			req.setAttribute("msg", "请登录之后在下单");
			return "/jsp/info.jsp";
		}
		// 获取购物车
		Cart cart = (Cart) req.getSession().getAttribute("cart");
		// 创建订单对象,为订单对象赋值
		Order order = new Order();
		order.setOid(UUIDUtils.getCode());
		order.setOrdertime(new Date());
		order.setTotal(cart.getTotal());
		order.setState(1);
		order.setUser(user);
		// 遍历购物项的同时,创建订单项,为订单项赋值
		for (CartItem item : cart.getCartItems()) {
			OrderItem orderItem = new OrderItem();
			orderItem.setItemid(UUIDUtils.getCode());
			orderItem.setQuantity(item.getNum());
			orderItem.setTotal(item.getSubTotal());
			orderItem.setProduct(item.getProduct());

			// 设置当前的订单项属于哪个订单:程序的角度体检订单项和订单对应关系
			orderItem.setOrder(order);
			order.getList().add(orderItem);
		}
		// 调用业务层功能:保存订单
		OrderService OrderService = new OrderServiceImp();
		// 将订单数据,用户的数据,订单下所有的订单项都传递到了service层
		OrderService.saveOrder(order);
		// 清空购物车
		cart.clearCart();
		// 将订单放入request
		req.setAttribute("order", order);
		// 转发/jsp/order_info.jsp
		return "/jsp/order_info.jsp";
	}
}

修改web.xml

web.xml中添加

<servlet>
  <description></description>
  <display-name>OrderServlet</display-name>
  <servlet-name>OrderServlet</servlet-name>
  <servlet-class>com.geekerstar.store.web.servlet.OrderServlet</servlet-class>
</servlet>
<servlet-mapping>
  <servlet-name>OrderServlet</servlet-name>
  <url-pattern>/OrderServlet</url-pattern>
</servlet-mapping>

在Cart.java中做如下修改

//返回MAP中所有的值
public Collection<CartItem> getCartItems(){
	return map.values();
}

在OrderService中创建方法

void saveOrder(Order order)throws Exception;

在OrderServiceImp中实现方法,用事务实现

package com.geekerstar.store.service.serviceImp;

import java.sql.Connection;
import java.sql.SQLException;
import java.util.List;

import com.geekerstar.store.dao.daoImp.OrderDaoImp;
import com.geekerstar.store.domain.Order;
import com.geekerstar.store.domain.OrderItem;
import com.geekerstar.store.domain.PageModel;
import com.geekerstar.store.domain.User;
import com.geekerstar.store.service.OrderService;
import com.geekerstar.store.utils.JDBCUtils;

public class OrderServiceImp implements OrderService {
	
	OrderDao orderDao=new OrderDaoImp();

	@Override
	public void saveOrder(Order order) throws SQLException {
		//保存订单和订单下所有的订单项(同时成功,失败)
		/*try {
			JDBCUtils.startTransaction();
			OrderDao orderDao=new OrderDaoImp();
			orderDao.saveOrder(order);
			for(OrderItem item:order.getList()){
				orderDao.saveOrderItem(item);
			}
			JDBCUtils.commitAndClose();
		} catch (Exception e) {
			JDBCUtils.rollbackAndClose();
		}
		*/
		
		Connection conn=null;
		try {
			//获取连接
			conn=JDBCUtils.getConnection();
			//开启事务
			conn.setAutoCommit(false);
			//保存订单
			
			orderDao.saveOrder(conn,order);
			//保存订单项
			for (OrderItem item : order.getList()) {
				orderDao.saveOrderItem(conn,item);	
			}
			//提交
			conn.commit();
		} catch (Exception e) {
			//回滚
			conn.rollback();
		}
	}
}

OrderDao中添加方法

void saveOrder(Connection conn, Order order)throws Exception;

void saveOrderItem(Connection conn, OrderItem item)throws Exception;

OrderDaoImp中实现两个方法

@Override
public void saveOrder(Connection conn, Order order) throws Exception {
	String sql="INSERT INTO orders VALUES(?,?,?,?,?,?,?,?)";
	QueryRunner qr=new QueryRunner();
	Object[] params={order.getOid(),order.getOrdertime(),order.getTotal(),order.getState(),order.getAddress(),order.getName(),order.getTelephone(),order.getUser().getUid()};
	qr.update(conn,sql,params);
}

@Override
public void saveOrderItem(Connection conn, OrderItem item) throws Exception {
	String sql="INSERT INTO orderitem VALUES(?,?,?,?,?)";
	QueryRunner qr=new QueryRunner();
	Object[] params={item.getItemid(),item.getQuantity(),item.getTotal(),item.getProduct().getPid(),item.getOrder().getOid()};
	qr.update(conn,sql,params);
}

修改订单详情页面

这是原来的订单详情页面,我们将对其做修改

order_info.jsp中获取订单信息,由于页面较多就不一一展示了,详情请看源码,并且原理和之前的一样,可以参考下面的图片进行修改。

效果演示

运行程序,添加两件商品到购物车,然后点击提交订单按钮

此时跳到这个页面

然后我们查看数据库,发现订单信息已经添加到数据库了,提交订单成功

源码下载

下载地址

导航目录

查看导航
丨极客文库, 版权所有丨如未注明 , 均为原创丨
本网站采用知识共享署名-非商业性使用-相同方式共享 3.0 中国大陆许可协议进行授权
转载请注明原文链接:Javaweb网上商城项目实战(22)提交订单模块
喜欢 (0)
[247507792@qq.com]
分享 (0)
Geekerstar
关于作者:
本站技术支持

您必须 登录 才能发表评论!

  • 精品技术教程
  • 编程资源分享
  • 问答交流社区
  • 极客文库知识库

客服QQ


QQ:2248886839


工作时间:09:00-23:00