一、sql
/* Navicat Premium Data Transfer Source Server : testOne Source Server Type : MySQL Source Server Version : 80028 Source Host : localhost:3306 Source Schema : miaosha Target Server Type : MySQL Target Server Version : 80028 File Encoding : 65001 Date: 20/04/2022 11:14:06 */ SET NAMES utf8mb4; SET FOREIGN_KEY_CHECKS = 0; -- ---------------------------- -- Table structure for sequence_info -- ---------------------------- DROP TABLE IF EXISTS `sequence_info`; CREATE TABLE `sequence_info` ( `name` varchar(255) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL, `current_value` int(0) NOT NULL DEFAULT 0, `step` int(0) NOT NULL DEFAULT 0, PRIMARY KEY (`name`) USING BTREE ) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_unicode_ci ROW_FORMAT = Dynamic; SET FOREIGN_KEY_CHECKS = 1; INSERT INTO `sequence_info`(`name`, `current_value`, `step`) VALUES ('order_info', 0, 1);
<!--sequence表--> <table tableName="sequence_info" domainObjectName="SequenceDO" enableCountByExample="false" enableUpdateByExample="false" enableDeleteByExample="false" enableSelectByExample="false" selectByExampleQueryId="false" enableInsert="true" enableDeleteByPrimaryKey="false"></table>
二、OrderServiceImpl
1 package com.miaoshaProject.service.impl; 2 3 import com.miaoshaProject.dao.OrderDOMapper; 4 import com.miaoshaProject.dao.SequenceDOMapper; 5 import com.miaoshaProject.dataobject.OrderDO; 6 import com.miaoshaProject.dataobject.SequenceDO; 7 import com.miaoshaProject.error.BusinessException; 8 import com.miaoshaProject.error.EnumBusinessError; 9 import com.miaoshaProject.service.ItemService; 10 import com.miaoshaProject.service.OrderService; 11 import com.miaoshaProject.service.UesrService; 12 import com.miaoshaProject.service.model.ItemModel; 13 import com.miaoshaProject.service.model.OrderModel; 14 import com.miaoshaProject.service.model.UserModel; 15 import org.springframework.beans.BeanUtils; 16 import org.springframework.beans.factory.annotation.Autowired; 17 import org.springframework.stereotype.Service; 18 import org.springframework.transaction.annotation.Propagation; 19 import org.springframework.transaction.annotation.Transactional; 20 21 import java.math.BigDecimal; 22 import java.time.LocalDateTime; 23 import java.time.format.DateTimeFormatter; 24 import java.util.Date; 25 26 /** 27 * @Author wangshuo 28 * @Date 2022/4/20, 9:35 29 * Please add a comment 30 */ 31 @Service 32 public class OrderServiceImpl implements OrderService { 33 34 @Autowired 35 OrderDOMapper orderDOMapper; 36 37 @Autowired 38 ItemService itemService; 39 40 @Autowired 41 UesrService uesrService; 42 43 @Autowired 44 SequenceDOMapper sequenceDOMapper; 45 46 @Override 47 @Transactional 48 public OrderModel createOrder(Integer userId, Integer itemId, Integer amount) throws BusinessException { 49 50 //校验下单状态 : 下单的商品是否存在,用户是否合法,购买数量是否正确 51 ItemModel itemModel = itemService.getItemById(itemId); 52 if (itemModel == null) 53 throw new BusinessException(EnumBusinessError.PARAMETER_VALIDATION_ERROR,"商品信息不存在"); 54 UserModel byId = uesrService.getById(userId); 55 if (byId == null) 56 throw new BusinessException(EnumBusinessError.PARAMETER_VALIDATION_ERROR,"用户信息不存在"); 57 if (amount <= 0 || amount > 99) 58 throw new BusinessException(EnumBusinessError.PARAMETER_VALIDATION_ERROR,"订单数量不正确"); 59 //落单减库存 60 boolean b = itemService.decreaseStock(itemId, amount); 61 if (!b) 62 throw new BusinessException(EnumBusinessError.STOCK_NOT_ENOUGH); 63 //订单入库 64 OrderModel orderModel = new OrderModel(); 65 orderModel.setUserId(userId); 66 orderModel.setItemId(itemId); 67 orderModel.setAmount(amount); 68 orderModel.setItemPrice(itemModel.getPrice()); 69 //相乘获得订单价格 70 orderModel.setOrderPrice(itemModel.getPrice().multiply(new BigDecimal(amount))); 71 //交易流水订单号 72 orderModel.setId(generateOrderNO()); 73 //转化model 74 OrderDO orderDO = convertFromOrderModel(orderModel); 75 //新增订单 76 orderDOMapper.insertSelective(orderDO); 77 //增加销量 78 itemService.increaseSales(orderModel); 79 //返回前端 80 return orderModel; 81 } 82 83 @Transactional(propagation = Propagation.REQUIRES_NEW)//不论外部事务成功与否 我这边都要提交事务,保证自增序列唯一性 84 public String generateOrderNO(){ 85 //设计 : 订单号有十六位, 86 StringBuilder stringBuilder = new StringBuilder(); 87 // 前八位为时间信息 88 LocalDateTime date = LocalDateTime.now(); 89 stringBuilder.append(date.format(DateTimeFormatter.ISO_DATE).replace("-", "")); 90 // 中间六位为自增序列 91 Integer sequence = 0; 92 //1.获取当前sequence 93 SequenceDO sequence_info = sequenceDOMapper.getSequenceByName("order_info"); 94 sequence = sequence_info.getCurrentValue(); 95 //2.sequence增加步长并入库 96 sequence_info.setCurrentValue(sequence_info.getCurrentValue() + sequence_info.getStep()); 97 sequenceDOMapper.updateByPrimaryKeySelective(sequence_info); 98 //3.拼接sequence 99 String sequenceStr = String.valueOf(sequence); 100 for (int i = 0; i < 6 - sequenceStr.length(); i++) {//当sequence被操作六位数以上后,中间自增序列就不止六位数了 101 stringBuilder.append(0); 102 } 103 stringBuilder.append(sequenceStr); 104 // 最后两位为分库分表位 暂时写死为00 105 stringBuilder.append("00"); 106 return stringBuilder.toString(); 107 } 108 109 private OrderDO convertFromOrderModel(OrderModel orderModel){ 110 111 if (orderModel == null) 112 return null; 113 OrderDO orderDO = new OrderDO(); 114 BeanUtils.copyProperties(orderModel,orderDO); 115 return orderDO; 116 } 117 }
三、ItemServiceImpl
1 package com.miaoshaProject.service.impl; 2 3 import com.miaoshaProject.dao.ItemDOMapper; 4 import com.miaoshaProject.dao.ItemStockDOMapper; 5 import com.miaoshaProject.dataobject.ItemDO; 6 import com.miaoshaProject.dataobject.ItemStockDO; 7 import com.miaoshaProject.error.BusinessException; 8 import com.miaoshaProject.error.EnumBusinessError; 9 import com.miaoshaProject.service.ItemService; 10 import com.miaoshaProject.service.model.ItemModel; 11 import com.miaoshaProject.service.model.OrderModel; 12 import com.miaoshaProject.validator.ValidationResult; 13 import com.miaoshaProject.validator.ValidatorImpl; 14 import org.springframework.beans.BeanUtils; 15 import org.springframework.beans.factory.annotation.Autowired; 16 import org.springframework.stereotype.Service; 17 import org.springframework.transaction.annotation.Transactional; 18 19 import java.util.List; 20 import java.util.stream.Collectors; 21 22 /** 23 * @Author wangshuo 24 * @Date 2022/4/19, 10:17 25 * Please add a comment 26 */ 27 @Service 28 public class ItemServiceImpl implements ItemService { 29 30 @Autowired 31 ValidatorImpl validator; 32 @Autowired 33 ItemDOMapper itemDOMapper; 34 @Autowired 35 ItemStockDOMapper itemStockDOMapper; 36 37 @Override 38 @Transactional//保证事务唯一性 39 public ItemModel createItem(ItemModel itemModel) throws BusinessException { 40 41 //校验入参 42 ValidationResult validator = this.validator.validator(itemModel); 43 if (validator.isHasErrors()) 44 throw new BusinessException(EnumBusinessError.PARAMETER_VALIDATION_ERROR, validator.getErrMsg()); 45 //转化model -》 dataObject 46 ItemDO itemDO = convertItemDOFromItemModel(itemModel); 47 itemDOMapper.insertSelective(itemDO); 48 itemModel.setId(itemDO.getId()); 49 ItemStockDO itemStockDO = convertItemStockDOFromItemModel(itemModel); 50 itemStockDOMapper.insertSelective(itemStockDO); 51 //返回创建完成的对象 52 return this.getItemById(itemDO.getId()); 53 } 54 55 @Override 56 public List<ItemModel> listItem() { 57 58 List<ItemDO> list = itemDOMapper.listItem(); 59 //java8 stream 将itemDO map成为 itemModel 60 List<ItemModel> modelList = list.stream().map(itemDO -> { 61 ItemStockDO itemStockDO = itemStockDOMapper.selectByItemId(itemDO.getId()); 62 ItemModel itemModel = convertModelFromDataObject(itemDO, itemStockDO); 63 return itemModel; 64 }).collect(Collectors.toList()); 65 return modelList; 66 } 67 68 @Override 69 public ItemModel getItemById(Integer id) { 70 71 ItemDO itemDO = itemDOMapper.selectByPrimaryKey(id); 72 if (itemDO == null) 73 return null; 74 //操作获得库存数量 75 ItemStockDO itemStockDO = itemStockDOMapper.selectByItemId(id); 76 //convert 77 ItemModel itemModel = convertModelFromDataObject(itemDO, itemStockDO); 78 return itemModel; 79 } 80 81 //减库存 82 @Override 83 @Transactional 84 public boolean decreaseStock(Integer itemId, Integer amount) throws BusinessException { 85 86 OrderModel orderModel = new OrderModel(); 87 orderModel.setItemId(itemId); 88 orderModel.setAmount(amount); 89 int affectedRow = itemStockDOMapper.decreaseStock(orderModel); 90 //影响条数大于0即为成功 91 return affectedRow > 0; 92 } 93 94 //加销量 95 @Override 96 @Transactional 97 public void increaseSales(OrderModel orderModel) throws BusinessException { 98 itemDOMapper.increaseSales(orderModel); 99 } 100 101 private ItemDO convertItemDOFromItemModel(ItemModel itemModel) { 102 103 if (itemModel == null) 104 return null; 105 ItemDO itemDO = new ItemDO(); 106 BeanUtils.copyProperties(itemModel, itemDO); 107 return itemDO; 108 } 109 110 private ItemStockDO convertItemStockDOFromItemModel(ItemModel itemModel) { 111 112 if (itemModel == null) 113 return null; 114 ItemStockDO itemStockDO = new ItemStockDO(); 115 itemStockDO.setItemId(itemModel.getId()); 116 itemStockDO.setStock(itemModel.getStock()); 117 return itemStockDO; 118 } 119 120 private ItemModel convertModelFromDataObject(ItemDO itemDO, ItemStockDO itemStockDO) { 121 122 ItemModel itemModel = new ItemModel(); 123 BeanUtils.copyProperties(itemDO, itemModel); 124 itemModel.setStock(itemStockDO.getStock()); 125 return itemModel; 126 } 127 }
四、mapping
<update id="increaseSales" parameterType="com.miaoshaProject.service.model.OrderModel"> <!-- WARNING - @mbg.generated This element is automatically generated by MyBatis Generator, do not modify. This element was generated on Mon Apr 18 09:20:26 CST 2022. --> update item set sales = sales + #{amount} where id = #{itemId} </update>
<update id="decreaseStock" parameterType="com.miaoshaProject.service.model.OrderModel"> update item_stock set stock = stock - #{amount} where item_id = #{itemId} and stock >= #{amount} </update>
<select id="getSequenceByName" parameterType="java.lang.String" resultMap="BaseResultMap"> <!-- WARNING - @mbg.generated This element is automatically generated by MyBatis Generator, do not modify. This element was generated on Wed Apr 20 11:11:22 CST 2022. --> select <include refid="Base_Column_List" /> from sequence_info where name = #{name,jdbcType=VARCHAR} for update </select>
五、OrderController
1 package com.miaoshaProject.controller; 2 3 import com.miaoshaProject.error.BusinessException; 4 import com.miaoshaProject.error.EnumBusinessError; 5 import com.miaoshaProject.response.CommonReturnType; 6 import com.miaoshaProject.service.OrderService; 7 import com.miaoshaProject.service.model.OrderModel; 8 import com.miaoshaProject.service.model.UserModel; 9 import org.springframework.beans.factory.annotation.Autowired; 10 import org.springframework.stereotype.Controller; 11 import org.springframework.web.bind.annotation.CrossOrigin; 12 import org.springframework.web.bind.annotation.RequestMapping; 13 import org.springframework.web.bind.annotation.RequestParam; 14 import org.springframework.web.bind.annotation.ResponseBody; 15 16 import javax.servlet.http.HttpServletRequest; 17 18 /** 19 * @Author wangshuo 20 * @Date 2022/4/20, 14:17 21 * Please add a comment 22 */ 23 @Controller("order") 24 @RequestMapping("/order") 25 @CrossOrigin(origins = {"*"}, allowCredentials = "true") 26 public class OrderController extends BaseController { 27 28 @Autowired 29 OrderService orderService; 30 @Autowired 31 HttpServletRequest request; 32 33 //封装下单请求 34 @RequestMapping("/create") 35 @ResponseBody 36 public CommonReturnType create(@RequestParam(name = "itemId") Integer itemId, 37 @RequestParam(name = "amount") Integer amount) throws BusinessException { 38 39 //获取user信息 40 Integer login_id = (Integer) this.request.getSession().getAttribute("LOGIN_USER"); 41 OrderModel orderModel = new OrderModel(); 42 if (login_id == null) { 43 /*throw new BusinessException(EnumBusinessError.USER_NOT_EXISTS,"用户未登录");*/ 44 orderModel = orderService.createOrder(17, itemId, amount); 45 } else 46 orderModel = orderService.createOrder(login_id, itemId, amount); 47 return CommonReturnType.create(orderModel); 48 } 49 }
六、getItem.html
<html> <head> <meta charset="UTF-8"> <link rel="stylesheet" href="assets/global/plugins/bootstrap/css/bootstrap.min.css" type="text/css"/> <link rel="stylesheet" href="assets/global/css/components.css" type="text/css"/> <link rel="stylesheet" href="assets/admin/pages/css/login.css" type="text/css"/> <script rel="stylesheet" src="assets/global/plugins/jquery-1.11.0.min.js" type="text/javascript"></script> </head> <body class="login" background="edge_bj_1.jpg"> <div class="content"> <h3 class="form-title">商品详情</h3> <div class="form-group"> <div> <label class="control-label" id="title"/> </div> </div> <div class="form-group"> <label class="control-label" style="font-size: 18px">商品描述</label> <div> <label class="control-label" id="description"/> </div> </div> <div class="form-group"> <div> <label class="control-label" id="price"/> </div> </div> <div class="form-group"> <div> <img style="width: 200px;height: auto" id="imgUrl"> </div> </div> <div class="form-group"> <label class="control-label" style="font-size: 18px">商品库存</label> <div> <label class="control-label" id="stock"/> </div> </div> <div class="form-group"> <label class="control-label" style="font-size: 18px">商品销量</label> <div> <label class="control-label" id="sales"/> </div> </div> <div class="from-actions"> <button class="btn blue" id="createorder" type="submit"> 下单 </button> </div> </div> </body> <script> function getParam(paramName) { paramValue = "", isFound = !1; if (this.location.search.indexOf("?") == 0 && this.location.search.indexOf("=") > 1) { arrSource = unescape(this.location.search).substring(1, this.location.search.length).split("&"), i = 0; while (i < arrSource.length && !isFound) arrSource[i].indexOf("=") > 0 && arrSource[i].split("=")[0].toLowerCase() == paramName.toLowerCase() && (paramValue = arrSource[i].split("=")[1], isFound = !0), i++ } return paramValue == "" && (paramValue = null), paramValue } function reloadDom() { $("#title").text(g_itemVO.title); $("#description").text(g_itemVO.description); $("#stock").text(g_itemVO.stock); $("#price").text(g_itemVO.price); $("#sales").text(g_itemVO.sales); $("#imgUrl").attr("src", g_itemVO.imgUrl); } var g_itemVO = {}; jQuery(document).ready(function () { //下单 $("#createorder").on("click", function () { $.ajax({ type: "POST", contentType: "application/x-www-form-urlencoded", url: "http://localhost:8080/order/create", data: { "itemId": g_itemVO.id, "amount": 1, }, dataType: "json", xhrFields: { withCredentials: true }, crossDomain: true, success: function (result) { if (result.status == "success") { alert("购买成功") //刷新界面 window.location.reload(); } else { alert("请求失败 原因为:" + result.data.errMsg) } }, error: function (result) { alert("请求失败 原因为" + result.responseText) } }) return false; }) //获取商品详情 $.ajax({ type: "GET", contentType: "application/x-www-form-urlencoded", url: "http://localhost:8080/item/get", data: { "id": getParam("id") }, dataType: "json", xhrFields: { withCredentials: true }, crossDomain: true, success: function (result) { if (result.status == "success") { g_itemVO = result.data; reloadDom(); } else { alert("请求失败 原因为:" + result.data.errMsg) } }, error: function (result) { alert("请求失败 原因为" + result.responseText) } }) }) </script> </html>
七、EnumBusinessError
1 package com.miaoshaProject.error; 2 3 /** 4 * @Author wangshuo 5 * @Date 2022/4/14, 8:43 6 * 自定义error 7 */ 8 public enum EnumBusinessError implements CommonError{ 9 //10001 参数不合法 10 PARAMETER_VALIDATION_ERROR(10001,"参数不合法"), 11 //20000 未知错误 12 UNKNOWN_ERROR(20000,"未知错误"), 13 //200001 登录超时或未登录 14 UN_LOGIN_ERROR(20001,"登录超时或未登录"), 15 //以30000 开头的错误码代表用户信息错误 16 USER_NOT_EXISTS(30001,"用户不存在"), 17 REGISTER_OTP_ERROR(30002,"验证码错误"), 18 REGISTER_REPEAT(30003,"该手机号已注册账户,请勿重复注册"), 19 LOGIN_ERROR(30004,"用户手机号或密码不正确"), 20 //以40000 开头的错误码代表交易错误 21 STOCK_NOT_ENOUGH(40001,"库存不足") 22 ; 23 24 private EnumBusinessError(Integer code,String msg){ 25 26 this.errorCode = code; 27 this.errorMsg = msg; 28 } 29 30 private int errorCode; 31 private String errorMsg; 32 33 @Override 34 public int getErrorCode() { 35 return this.errorCode; 36 } 37 38 @Override 39 public String getErrorMsg() { 40 return this.errorMsg; 41 } 42 43 //定制化的方法改动错误信息 44 @Override 45 public CommonError setErrorMsg(String msg) { 46 this.errorMsg = msg; 47 return this; 48 } 49 }
本文来自博客园,作者:荣慕平,转载请注明原文链接:https://www.cnblogs.com/rongmuping/articles/16172664.html