Java Web 网络商城案例演示十四(设计订单表)
订单模块
1、模型的抽取
2、提交订单
3、查询我的订单
4、订单详情
5、支付功能
6、权限过滤器
一、模型的抽取
订单:本次交易记录,描述
1、分析超市小票:
设计一个表,存储小票上的数据
第一种方式:
弊端:数据冗余严重
DB原则:存储最少的数据,办更多的事情
第二种方式
一个表专注于交易的描述,订单表orders
Ordes表中的会员id列参照了用户表上的uid
订单状态:
买家:下单未付款,付款未发货,以发货,签收
卖家:下单未付款,发货,未签收,已收货(结束)
另外一个表专注于每笔订单的一个详细的交易情况,订单项orderitem
orderitem表中的商品的id,所在订单编号是参照了商品表订单id的商品pid(流水号)
分析提交订单:
用户点击提交订单,将购物车当中的数据以订单/订单项的形式保存下来。清空购物车
保存订单:
为订单表中插入一行数据,描述本次交易,这行数据部分数据是通过程序赋予的,部分数据是来自购物车的,部分数据是来自session中的用户
数据库当中创建表
1、订单表orders
其中:
oid:UUIDUtils
orderTime:new Date();
total:从购物车获取
state:1
address:null
name:null
telephone:null
uid:从session中的用户获取到
保存订单项:
向订单项表中插入数据,描述当前订单的一个详细的购买信息,部分数据是来自购物车,部分数据需要通过程序赋予。
2、订单表orderitem
提交的商品表
itemid:UUIDUtils
uid:来自于购物车中的购物项
total:来自购物车中的购物项
pid:来自购物车上购物项下商品对象的pid
oid:来自于当前订单的id
提交订单时,订单以及订单项必须同时成功(事务)
用户点击提交订单,将购物车中的数据以订单/订单的形式保存来,然后清空购物车
保存订单:
为订单表中插入一行数据,描述本次及交易,这行数据部分数据是通过程序赋予的,部分数据来自购物车,部分数据来自session中的用户
步骤实现
创建OrderServlet OrderService OrderServiceImpl OrderDaoImpl
Order{User user,List list = new ArrayList}
OrderItem{Product product,Order order}
创建Order{User user,List list = new ArrayList}
public class Order {
private String oid; //订单编号
private Date ordertime; //下单时间
private double total; //总计
private int state; //状态
private String address; //收货人地址
private String name; //收货人姓名
private String telephone; //收货人电话
//程序对象和对象发送关系,而不是对象和对象的属性发送关系
//设计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;
}
public Order() {
// TODO Auto-generated constructor stub
}
public Order(String oid, Date ordertime, double total, int state, String address, String name, String telephone,
User user, List<OrderItem> list) {
super();
this.oid = oid;
this.ordertime = ordertime;
this.total = total;
this.state = state;
this.address = address;
this.name = name;
this.telephone = telephone;
this.user = user;
this.list = list;
}
@Override
public String toString() {
return "Order [oid=" + oid + ", ordertime=" + ordertime + ", total=" + total + ", state=" + state + ", address="
+ address + ", name=" + name + ", telephone=" + telephone + ", user=" + user + ", list=" + list + "]";
}
}
创建OrderItem{Product product,Order order}
package cn.itzheng.store.domain;
public class OrderItem {
private String itemid;// id
private int quantity; // 数量
private double total;// 小计
// 1、对象对应对象
// 2、product,order携带更多的数据
private Product product;// 获取其对象上的商品ip即为pid
private Order order;// 获取对象上的oid,当前订单id
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;
}
public OrderItem() {
// TODO Auto-generated constructor stub
}
public OrderItem(String itemid, int quantity, double total, Product product, Order order) {
super();
this.itemid = itemid;
this.quantity = quantity;
this.total = total;
this.product = product;
this.order = order;
}
@Override
public String toString() {
return "OrderItem [itemid=" + itemid + ", quantity=" + quantity + ", total=" + total + ", product=" + product
+ ", order=" + order + "]";
}
}
创建OrderServlet
创建saveOrder方法
确认用户登录状态
创建订单对象,为订单对象赋值
遍历购物项的同时,创建订单项
调用业务层功能:保存订单
清空购物车
将订单放入request
转发/jsp/order_info.jsp
return “/jsp/order_info.jsp”;
public class OrderServlet extends BaseServlet {
// saveOrder 将购物车中的信息以订单的形式保存
public String saveOrder(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException, SQLException {
// TODO Auto-generated method stub
// 确认用户登录状态 从session当中获取对应user
User user = (User) request.getSession().getAttribute("loginUser");
if (null == user) {
request.setAttribute("msg", "请登录之后在下单");
return "/jsp/info.jsp";
}
// 从session作用域当中获取购物车
Cart cart = (Cart) request.getSession().getAttribute("cart");
// 创建订单对象,为订单对象赋值
Order order = new Order();
order.setOid(UUIDUtils.getCode());// oid获取随机的
order.setOrdertime(new Date());// 获取当前时间
order.setTotal(cart.getTotal());// 获取当前总金额
order.setState(1);
order.setUser(user);// 将当前用户放入到订单当中
// 遍历购物项的同时,创建订单项,为订单项赋值
for (CartItem item : cart.getCartItems()) {// 遍历购物车当中的购物项,cart.getCartItems():获取到购物车当中所有的商品的集合
OrderItem orderItem = new OrderItem();
orderItem.setItemid(UUIDUtils.getCode());// 设置商品编号
orderItem.setQuantity(item.getNum());// 设置订单的商品的数量是Cart当中CartItem商品项的数量
orderItem.setTotal(item.getSubTotal());//将商品的小计设置搭配订单项的金额当中
orderItem.setProduct(item.getProduct());//获取到商品项当中的每一个商品,将商品项放入到订单项当中
//设置当前的订单项属于那个订单:程序的角度体验订单订单项和订单对应关系
orderItem.setOrder(order);//将订单放入到订单项当中,以便获取订单编号
order.getList().add(orderItem);//将每一个订单项放入的到对应的订单当中
}
//调用业务层功能,保存订单
OrderService orderService = new OrderServiceImpl();
//将订单数据,用户数据,订单下所有的订单项都传递到service层
orderService.saveOrder(order);
//清空购物车
cart.clearCart();
//将订单信息放入request
request.setAttribute("order", order);
//转发到/jsp/order_info.jsp
return "/jsp/order_info.jsp";
}
}
OrderService
public interface OrderService {
void saveOrder(Order order) throws SQLException;
}
OrderServiceImpl
public class OrderServiceImpl implements OrderService {
OrderDao orderDao = new OrderDaoImpl();
@Override
public void saveOrder(Order order) throws SQLException {
/*
* try { //保存订单和订单下所有的订单项(同时成功或者同时失败) //开启数据的事务 JDBCUtils.startTransaction();
* OrderDao orderDao = new OrderDaoImpl();
*
* orderDao.saveOrder(order);
*
* for(OrderItem item:order.getList()) {//遍历所有的订单项 orderDao.saveOrderItem(item);
* }
*
*
* } catch (Exception e) { // TODO: handle exception
* JDBCUtils.commitAndClose();//关闭事务 }
*/
Connection conn = null;
try {
//获取到链接
conn = JDBCUtils.getConnection();
//开启事务
conn.setAutoCommit(false);//开启事务
//保存订单
orderDao.savaOrder(conn,order);
//保存订单项
//遍历订单上的每一个购物项
for(OrderItem item:order.getList()) {
orderDao.savaOrderItem(conn,item);
}
//提交事务
conn.commit();
} catch (Exception e) {
// TODO: handle exception
//如果有异常
//回滚事务
conn.rollback();
}
}
}
OrderDao
public interface OrderDao {
void savaOrderItem(Connection conn, OrderItem item) throws SQLException;
void savaOrder(Connection conn, Order order)throws SQLException;
}
public class OrderDaoImpl implements OrderDao {
// 保存订单
@Override
public void savaOrder(Connection conn, Order order) throws SQLException {
// TODO Auto-generated method stub
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 savaOrderItem(Connection conn, OrderItem item) throws SQLException {
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);
}
}
修改/jsp/order_info.jsp
我的订单查询
原理分析:
步骤实现
1、准备工作:
在header.jsp
<li><a href="${pageContext.request.contextPath}/OrderServlet?method=findMyOrdersWithPage&num=1">我的订单</a></li>
2、OrderServlet—>findMyOrdersWithPage
获取用户信息
获取当前页
调用业务层功能:查询当前用户订单信息,返回PageModel
将PageModel放入request
转发到/jsp/order_list.jsp
3、OrderService当中实现findMyOrdersWithPage方法
public interface OrderService {
PageModel findMyOrdersWithPage(User user, int curNum)throws SQLException;
}
4、OrderService当中实现findMyOrdersWithPage方法
@Override
public PageModel findMyOrdersWithPage(User user, int curNum) throws SQLException {
// 1、创建PageModel对象,目的:接收并且携带分页参数
//select count(*) from orders where uid = ? 统计当前用户的所有订单
int totalRecords = orderDao.getTotalRecords(user);
PageModel pm = new PageModel(curNum, totalRecords, 3);
//2、关联集合 select * from orders where uid = ? limit ?,?;
List list = orderDao.findMyOrdersWithPage(user,pm.getStartIndex(),pm.getPageSize());
pm.setList(list);
//3、关联url
pm.setUrl("OrderServlet?method=findMyOrdersWithPage");
return pm;
}
5、在OrderDao当中实现findMyOrdersWithPage
public interface OrderDao {
List findMyOrdersWithPage(User user, int startIndex, int pageSize)throws SQLException;
}
在OrderDaoImpl 当中实现findMyOrdersWithPage
public class OrderDaoImpl implements OrderDao {
@Override
public List findMyOrdersWithPage(User user, int startIndex, int pageSize) throws SQLException {
// TODO Auto-generated method stub
String sql = "select * from orders where uid = ? limit ?,?";
QueryRunner qr = new QueryRunner(JDBCUtils.getDataSource());
// 获取到分页信息相关的list集合(Order集合)
List<Order> list = qr.query(sql, new BeanListHandler<Order>(Order.class), user.getUid(), startIndex, pageSize);
// 遍历所有订单
for (Order order : list) {
// 获取到每笔订单oid 查询每笔订单下订单项以及订单项对应的商品信息
String oid = order.getOid();
// SELECT * FROM orderItem,product返回的是笛卡尔集
// 商品编号必须匹配(保证是同一个商品) 并通过的是oid来查询即订单编号来查询
sql = "select * from orderItem o ,product p where o.pid=p.pid and oid=?";
List<Map<String, Object>> list02 = qr.query(sql, new MapListHandler(), oid);// 获取到的是笛卡尔集的所有对应的商品集合
// 遍历list集合
for (Map<String, Object> map : list02) {
// 实例化
OrderItem orderItem = new OrderItem();
Product product = new Product();
// 由于BeanUtlis将字符串“1992-3-3”向user对象的setBithday();方法传递参数有问题,手动向BeanUtils注册一个时间类型转换器
// 1、创建时间类型的转换器
DateConverter dt = new DateConverter();
// 2、设置转换的格式
dt.setPattern("yyyy-MM-dd");
// 3、注册转换器
ConvertUtils.register(dt, Date.class);// 将Date对象设置为dt当中的格式
try {
// 将map中属于orderItem的数据自动填充到orderItem对象上
BeanUtils.populate(orderItem, map);
// 将map中属于product的数据自动填充到product对象上
BeanUtils.populate(product, map);
// 让每一个订单项和商品项发生关系
orderItem.setProduct(product);// 将商品项当中的内容放到订单项当中
order.getList().add(orderItem);// 将订单项放到订单当中的list集合当中
} catch (IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InvocationTargetException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
// 根据订单id,查询当前订单下所有的订单项以及订单项对应的商品信息
// select * from product;
}
return list;
}
6、在order_list.jsp
遍历数据时,2个循环,大循环遍历订单,小循环遍历的是订单上的订单项
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<!doctype html>
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>会员登录</title>
<link rel="stylesheet" href="${pageContext.request.contextPath}/css/bootstrap.min.css" type="text/css" />
<script src="${pageContext.request.contextPath}/js/jquery-1.11.3.min.js" type="text/javascript"></script>
<script src="${pageContext.request.contextPath}/js/bootstrap.min.js" type="text/javascript"></script>
<!-- 引入自定义css文件 style.css -->
<link rel="stylesheet" href="${pageContext.request.contextPath}/css/style.css" type="text/css"/>
<style>
body {
margin-top: 20px;
margin: 0 auto;
}
.carousel-inner .item img {
width: 100%;
height: 300px;
}
</style>
</head>
<body>
<%@ include file="/jsp/header.jsp" %>
<div class="container">
<div class="row">
<div style="margin:0 auto; margin-top:10px;width:950px;">
<strong>我的订单</strong>
<table class="table table-bordered">
<c:forEach items="${page.list}" var="o">
<tbody>
<tr class="success">
<th colspan="5">
订单编号:${o.oid}
总金额:¥${o.total}元
<c:if test="${o.state==1}">
<a href="${pageContext.request.contextPath}/OrderServlet?method=findOrderByOid&oid=${o.oid}">付款</a>
</c:if>
<c:if test="${o.state==2}">未发货</c:if>
<c:if test="${o.state==3}">
<a href="">签收</a>
</c:if>
<c:if test="${o.state==4}">结束</c:if>
</th>
</tr>
<tr class="warning">
<th>图片</th>
<th>商品</th>
<th>价格</th>
<th>数量</th>
<th>小计</th>
</tr>
<c:forEach items="${o.list}" var="item">
<tr class="active">
<td width="60" width="40%">
<input type="hidden" name="id" value="22">
<img src="${pageContext.request.contextPath}/${item.product.pimage}" width="70" height="60">
</td>
<td width="30%">
<a target="_blank">${item.product.pname}</a>
</td>
<td width="20%">
¥${item.product.shop_price}
</td>
<td width="10%">
${item.quantity}
</td>
<td width="15%">
<span class="subtotal">¥${item.total}</span>
</td>
</tr>
</c:forEach>
</tbody>
</c:forEach>
</table>
<%@ include file="/jsp/pageFile.jsp" %>
</div>
</div>
</div>
<%@ include file="/jsp/footer.jsp" %>
</body>
</html>