如果说一个商品管理系统最重要的模块之一是什么,那么我首先会说订单模块,它代表着我们商品的售卖情况,是商家最关心的地方,今天我们开始学习订单是如何创建的
2023/11/21
1.将购物车数据变为订单数据
前面我们提到我们将用户随手添加的产品放入到缓存中来应对用户每次的变化,因为每次用户点的菜品可能都不一样,所有使用缓存可以降低我们的内存消耗,但是一旦用户决定将购物车中的商品变为真实的订单,那么我们就需要将数据放入到我们的数据库中。
由此,我们需要建立数据库表order和order_details
CREATE TABLE orders (
id INT AUTO_INCREMENT PRIMARY KEY,
user_id INT NOT NULL,
total_price INT,
status String,
order_date TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
);
order表中包含我们的用户id,此张订单的总价格,订单状态,创建订单的时间
CREATE TABLE `order_details` (
`order_details_id` INT NOT NULL AUTO_INCREMENT,
`order_id` INT NOT NULL,
`cai_name` INT NOT NULL,
`quantity` INT NOT NULL,
`price` INT NOT NULL,
PRIMARY KEY (`order_details_id`),
FOREIGN KEY (`order_id`) REFERENCES `order` (`order_id`) on delete cascade
);
order_details表中包含订单id作为外键,若订单删除,那么对应订单id的所有订单详情会同时被删除,cai_name,quantity用来记录菜品的名字和数量,price记录菜品对应的价格,后续我们在订单表中计算总价格;
2.创建订单相关实体和方法
我们创建完了order和order_details之后,在java中创建对应的实体和方法以及xml,具体的逻辑在前面的基础中已经很熟练了,其中用到的方法是边做边加的,用什么直接新增一个方法就好,直接放代码,展示一下两个serverice实现类
@Service
public class OrderServiceImpl implements OrderService {
@Autowired
private OrderMapper orderMapper;
public void insertOrder(Order order){
orderMapper.insertOrder(order);
}
@Override
public int selectIdbyuser(int user_id) {
return orderMapper.selectIdbyuser(user_id);
}
@Override
public void updataOrderPriceByid(int order_id,int total_price) {
orderMapper.updataOrderPriceByid(order_id,total_price);
}
}
@Service
public class OrderDetailServiceImpl implements OrderDetailService {
@Autowired
private OrderDetailsMapper orderDetailsMapper;
@Override
public void insertOrderDetails(OrderDetails orderDetails) {
orderDetailsMapper.insertOrderDetails(orderDetails);
}
@Override
public int gettotalprice(int order_id) {
return orderDetailsMapper.gettotalprice(order_id);
}
}
其实方法是很简单的,我们主要复杂的地方是在于我们处理的逻辑,也就是controller,下面会从逻辑的角度来细解实现的过程
3.实现订单创建逻辑
在之前我们已经创建好了购物车,接下来我们要把购物车中的数据发送到后端,需要先新增一个按钮,点击提交订单发送fetch请求,此处与前面的学习都差不多,直接放代码即可
//在我们的购物车模拟框中加入一个按钮
<button type="submit" th:onclick="createOrder()">提交订单</button>
<script>
function createOrder(){
fetch('/createOrder',{
method:'POST'
}).then(res=>res.json())
.then(res=>{document.getElementById("carModal").style.display = 'none';
alert(res.message);
}).catch(err=>console.error("上传失败请重试"+err))
}
</script>
前端发送请求后,后端首先使用session验证用户身份,然后通过用户姓名来找到对应的redis购物车数据,这里说明一下我们之前是在购物车中放了菜品的名字和数量(小修改),接下来创建一个新的order,设置它的userid,状态为已创建,创建时间,这三个字段,这时mysql会自动为我们创建一个orderid我们查询这个id,因为我们后面要存入到详情表中,此时order还有一个total_price没有被设置,因为我们缺少订单详情,所以后面更新它即可。这部分代码如下:
@PostMapping("/createOrder")
public ResponseEntity<Map<String,String>> createOrder( HttpSession session){
String username = (String) session.getAttribute("USER");
System.out.println(username);
int userid = userService.selectUserID(username);
System.out.println(userid);
if (username==null){
Map<String,String> response = new HashMap<>();
response.put("message","用户未登录");
return ResponseEntity.badRequest().body(response);
}
Order order = new Order();
order.setUser_id(userid);
order.setStatus("已提交订单");
order.setOrder_date(LocalDateTime.now());
System.out.println(LocalDateTime.now());
orderService.insertOrder(order);
接着我们根据redis中的购物车数据来更新订单详情表,使用hashoperation的entries方法,我们可以获取到一个hashmap的所有键值对,然后使用for-each也叫增强for循环来遍历entries,这里我们计算total_price的方法是在for循环外面初始化一个值,然后在for循环中累加,这样可以每次循环后保留计算好的total_price;我们将entry的每个键作为cai_name,每个value作为quantity,然后同时将之前定义好的cai_id,order_id以及从菜品表查到的菜品价格加入到详情表中,详情表就更新完成了,我们最后把这个order_id所对应的total_price更新到订单表中,这样两个表的字段就全部更新完成了,此时我们可以将之前没有设置过期时间的购物车redis缓存给删除,这样订单和购物车就只会存在一个了,代码如下(续上):
int orderid = orderService.selectIdbyuser(userid);
System.out.println(orderid);
String carkey = "car" + username;
hashOperations = redisTemplate.opsForHash();
Map<Object,Object> car = hashOperations.entries(carkey);
int total_price = 0;
for (Map.Entry<Object,Object> entry : car.entrySet()){
String cai_name = (String) entry.getKey();
int quantity = (int) entry.getValue();
OrderDetails orderDetails = new OrderDetails();
System.out.println(orderid);
orderDetails.setOrder_id(orderid);
orderDetails.setCai_name(cai_name);
orderDetails.setQuantity(quantity);
int price = caiService.selectPriceByName(cai_name);
orderDetails.setPrice(price);
orderDetailService.insertOrderDetails(orderDetails);
int item_price = quantity * price;
total_price = total_price+item_price;
}
System.out.println("总价格为:"+total_price);
// int totalprice = orderDetailService.gettotalprice(orderid);
orderService.updataOrderPriceByid(orderid,total_price);
redisTemplate.delete(carkey);
Map<String,String> response = new HashMap<>();
response.put("message","订单已创建");
return ResponseEntity.ok().body(response);
}
4.实现效果图
点击提交订单-发送数据到后端-模拟框关闭
更新订单详情表,此时我们oder_id对应是50的是本次订单
更新订单表价格,通过详情表的菜品数量和价格,我们将计算好的总金额更新到订单表
提交订单后,再次进入购物车,数据已经消失