文章目录
- 第八阶段-订单模块
- Step1:构建数据库表
- Step2:构建pojo类对象
- Step3:Dao层的编写与测试
- Step4:Service层的编写与测试
- Step5:Web层的编写与测试
第八阶段-订单模块
由订单界面分析订单的模型分析可得到如下的功能分析图。具体地,一个Order订单中会包含多个订单项,同一个订单中的各个订单项的订单号也是相同的。由于订单项是参考订单id的(外键),因此需要先由Order订单,再有订单中的各个订单项
Step1:构建数据库表
根据数据库关系模型关系,可构建订单表以及订单项表。其中订单表涉及订单号,下单时间,价格,状态,用户id的信息,每一个订单项对应唯一的订单号(外键),同时订单项由自身id,商品名称,价格,总价。
create table t_order(
`order_id` varchar(50) primary key ,
`create_time` datetime,
`price` decimal(11,2),
`status` int,
`user_id` int,
foreign key (`user_id`) references t_user(`id`)
);
create table t_order_item(
`id` int primary key auto_increment,
`name` varchar(100),
`count` int,
`price` decimal(11,2),
`total_price` decimal(11,2),
`order_id` varchar(50),
foreign key (`order_id`) references t_order(`order_id`)
)
Step2:构建pojo类对象
基于上述数据库表,可以在pojo中构建order类以及orderItem类
order类
public class Order {
private String orderId;
private Date creatTime;
private BigDecimal price;
//0 未发货 1 已发货 2 已签收
private Integer status = 0;
private Integer userId;
public Order() {
}
public Order(String orderId, Date creatTime, BigDecimal price, Integer status, Integer userId) {
this.orderId = orderId;
this.creatTime = creatTime;
this.price = price;
this.status = status;
this.userId = userId;
}
//getset方法
}
orderItem类
public class OrderItem {
private Integer id;
private String name;
private Integer count;
private BigDecimal price;
private BigDecimal totalPrice;
private String orderId;
public OrderItem() {
}
public OrderItem(Integer id, String name, Integer count, BigDecimal price, BigDecimal totalPrice, String orderId) {
this.id = id;
this.name = name;
this.count = count;
this.price = price;
this.totalPrice = totalPrice;
this.orderId = orderId;
}
// getset方法
}
Step3:Dao层的编写与测试
根据上述分析,在Dao层调用了生成订单的方法后就会在数据控中创建一个订单以及订单项的的sql语句为:
insert into t_order(`order_id`, `creat_time`, `price`, `status`, `user_id`) values(?,?,?,?,?)
insert into t_order_item(`name`, `count`, `price`, `total_price`, `order_id`) values(?,?,?,?,?)
因此,Dao层的传入数据应当是一个order
对象以及orderItem
对象
先定义接口规范,这里以保存订单为例
public interface OrderDao {
public int saveOrder(Order order);
}
public interface OrderItemDao {
public int saveOrderItem(OrderItem orderItem);
}
对应的实现类代码如下:
/*
* 在数据库中保存一个订单,需要传入一个order对象
*/
public class OrderDaoImpl extends BaseDao implements OrderDao {
@Override
public int saveOrder(Order order) {
System.out.println("OrderDaoImpl 程序在[" +Thread.currentThread().getName() + "]中");
String sql = "insert into t_order(`order_id`, `creat_time`, `price`, `status`, `user_id`) values(?,?,?,?,?)";
int i = update(sql, order.getOrderId(), order.getCreatTime(), order.getPrice(), order.getStatus(), order.getUserId());
return i;
}
}
/*
* 在数据库中保存一个订单项,需要传入一个orderItem对象
*/
public class OrderItemDaoImpl extends BaseDao implements OrderItemDao {
@Override
public int saveOrderItem(OrderItem orderItem) {
System.out.println(" OrderItemDaoImpl 程序在[" +Thread.currentThread().getName() + "]中");
String sql = "insert into t_order_item(`name`, `count`, `price`, `total_price`, `order_id`) values(?,?,?,?,?)";
int i = update(sql, orderItem.getName(), orderItem.getCount(), orderItem.getPrice(), orderItem.getTotalPrice(), orderItem.getOrderId());
return i;
}
}
Step4:Service层的编写与测试
在Service层灰调用Dao层,Service层的createOrder()
方法需要给Dao层传递一个order
对象,同时返回该order
对象的订单号。其需要从Web层获取购物车对象以及用户的id信息,从而完成order
对象以及orderItem
对象的封装。在这一层中涉及OrderDao
、OrderItemDao
以及bookDao
三个Dao对象的方法。
首先写Service层的接口规范
public interface OrderService {
public String creatOrder(Cart cart, Integer userId);
}
实现流程如下:
- 利用从Web层中得到的购物车对象
cart
,以及当前用户Id
生成唯一的订单号信息OrderId
- 利用订单号
OrderId
创建一个order
对象,并将调用orderDao层的orderSave()
方法该对象保存至数据库 - 遍历当前购物车中的每个数据项,利用相关信息创建
orderItem
项,并调用orderItemSave()
方法将这些对象都依次保存至数据库中 - 调用
book.setSales()
方法更新数据库中图书的库存和销量信息 - 清空购物车,返回订单号
上述过程对应代码如下;
public class OrderServiceImpl implements OrderService {
private OrderDao orderDao = new OrderDaoImpl();
private OrderItemDao orderItemDao = new OrderItemDaoImpl();
private BookDao bookDao = new BookDaoImpl();
@Override
public String creatOrder(Cart cart, Integer userId) {
// 订单号===唯一性
String orderId = System.currentTimeMillis() + "" + userId;
// 创建一个订单对象
Order order = new Order(orderId, new Date(), cart.getTotalPrice(), 0, userId);
// 保存订单
orderDao.saveOrder(order);
// 遍历购物车中每一个商品项转换成为订单项保存到数据库
for (Map.Entry<Integer, CartItem> entry : cart.getItems().entrySet()) {
// 获取每一个购物车中的商品项
CartItem cartItem = entry.getValue();
// 转换为每一个订单项
OrderItem orderItem = new OrderItem(null, cartItem.getName(), cartItem.getCount(), cartItem.getPrice(), cartItem.getTotalPrice(), orderId);
// 保存订单项到数据库
orderItemDao.saveOrderItem(orderItem);
// 更新库存和销量
Book book = bookDao.queryBookById(cartItem.getId());
book.setSales(book.getSales() + cartItem.getCount());
book.setSales(book.getStock() - cartItem.getCount());
bookDao.updateBook(book);
}
// 清空购物车
cart.clear();
return orderId;
}
}
Step5:Web层的编写与测试
Web层中,需要获取用户的点击信息(在购物车页面点击结算按钮),同时将当前页面信息展示为订单号
具体步骤如下:
- 获取当前用户对应的
session
中的cart
对象,以及用户的id信息
- 如果当前用户信息为空,让其进入登陆页面
- 调用Service层的
creatOrder()
方法并获取对应的订单编号信息 - 将订单编号信息保存至
Session
域中并将响应重定向至/pages/cart/checkout.jsp
页面。
对应源码如下:
protected void creatOrder(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 先获取Cart购物车对象
Cart cart = (Cart)request.getSession().getAttribute("cart");
// 获取Userid
User loginUser = (User)request.getSession().getAttribute("user");
if (loginUser == null) {
request.getRequestDispatcher("/pages/user/login.jsp").forward(request, response);
return;
}
Integer userId = loginUser.getId();
// 调用orderService.createOrder(Cart,Userid);生成订单
String orderId = orderService.createOrder(cart, userId);
request.getSession().setAttribute("orderId", orderId);
response.sendRedirect(request.getContextPath() + "/pages/cart/checkout.jsp");
}