mirror of
				https://gitee.com/coder-xiaomo/flashsale
				synced 2025-11-04 14:13:14 +08:00 
			
		
		
		
	交易下单1(未完成)
This commit is contained in:
		
							
								
								
									
										28
									
								
								README.md
									
									
									
									
									
								
							
							
						
						
									
										28
									
								
								README.md
									
									
									
									
									
								
							@@ -18,7 +18,7 @@
 | 
			
		||||
| ----------------- | --------------------- | --------------------------------------- | ---------------------------------------- | ------------------------------- |
 | 
			
		||||
| **Controller层**  |                       |                                         |                                          |                                 |
 | 
			
		||||
| Controller        | controller            | 类 class                                |                                          | controller.UserController       |
 | 
			
		||||
| View Object       | controller/viewobject | 类 class                                | 将用户Model转化为可供UI使用的View Object | controller.UserController       |
 | 
			
		||||
| View Object (VO)  | controller/viewobject | 类 class                                | 将用户Model转化为可供UI使用的View Object | controller.UserController       |
 | 
			
		||||
|                   |                       |                                         |                                          |                                 |
 | 
			
		||||
| **Service层**     | 转换成业务模型        |                                         |                                          |                                 |
 | 
			
		||||
| Service           | service               | 接口 interface                          |                                          | service.UserService             |
 | 
			
		||||
@@ -28,7 +28,7 @@
 | 
			
		||||
| **Dao层**         | 对数据库的映射        |                                         |                                          |                                 |
 | 
			
		||||
| Mapper            | dao                   | 接口 interface                          |                                          | dao.UserDOMapper                |
 | 
			
		||||
| Mapping           | resources/mapping     | Mapper接口实现类                        | xml格式;SQL语句                         | mapping/UserDOMapper.xml        |
 | 
			
		||||
| Data Object       | dataobject            | 类 class                                |                                          | dataobject.UserDO               |
 | 
			
		||||
| Data Object (DO)  | dataobject            | 类 class                                |                                          | dataobject.UserDO               |
 | 
			
		||||
|                   |                       |                                         |                                          |                                 |
 | 
			
		||||
| **其他**          |                       |                                         |                                          |                                 |
 | 
			
		||||
| response          | response              |                                         | 用于处理HTTP请求返回                     | response.CommonReturnType       |
 | 
			
		||||
@@ -41,3 +41,27 @@
 | 
			
		||||
| BusinessException | error                 | CommonError接口实现类 & 继承自Exception |                                          | error.BusinessException         |
 | 
			
		||||
 | 
			
		||||
**Tips:** Model与Data Object并非完全一一对应,例如UserModel是由ServiceImpl将UserDO和UserPasswordDO组装而成的。
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
代码构建顺序:
 | 
			
		||||
 | 
			
		||||
1. 创建Model模型(service/model)
 | 
			
		||||
 | 
			
		||||
2. 创建数据库中数据表
 | 
			
		||||
 | 
			
		||||
3. 使用mybatis-generator生成数据库映射文件(dao ; dataobject ; resources/mapping)
 | 
			
		||||
 | 
			
		||||
4. 创建Service接口(service)
 | 
			
		||||
 | 
			
		||||
5. 创建Service接口实现Impl(service/impl)(class打上 `Service` 标注;方法上打上 `@Transactional` 标签保证是在同一事务中)
 | 
			
		||||
 | 
			
		||||
6. 思考ServiceImpl中需要哪几步,并逐步实现
 | 
			
		||||
 | 
			
		||||
   > - 如果需要修改自动生成的数据库语句,先改 resources/mapping 下的xml映射SQL语句,然后修改 dao 下的DOMapper接口
 | 
			
		||||
   >
 | 
			
		||||
   > - 可以用 `org.springframework.beans` 包中的 `BeanUtils.copyProperties` 进行DO转Model或Model转DO(要字段和类型完全一致的字段才能拷贝,其他不对应字段的需要手动设置)
 | 
			
		||||
 | 
			
		||||
7. 
 | 
			
		||||
 | 
			
		||||
8. Service返回Controller前将DO
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,7 @@
 | 
			
		||||
package com.cxyxiaomo.flashsale.dao;
 | 
			
		||||
 | 
			
		||||
import com.cxyxiaomo.flashsale.dataobject.ItemStockDO;
 | 
			
		||||
import org.apache.ibatis.annotations.Param;
 | 
			
		||||
 | 
			
		||||
public interface ItemStockDOMapper {
 | 
			
		||||
    /**
 | 
			
		||||
@@ -52,4 +53,6 @@ public interface ItemStockDOMapper {
 | 
			
		||||
     * @mbg.generated Thu Mar 03 13:12:13 CST 2022
 | 
			
		||||
     */
 | 
			
		||||
    int updateByPrimaryKey(ItemStockDO record);
 | 
			
		||||
 | 
			
		||||
    int decreaseStock(@Param("itemId") Integer itemId, @Param("amount") Integer amount);
 | 
			
		||||
}
 | 
			
		||||
@@ -1,13 +1,16 @@
 | 
			
		||||
package com.cxyxiaomo.flashsale.error;
 | 
			
		||||
 | 
			
		||||
public enum EmBusinessError implements CommonError {
 | 
			
		||||
    // 通用错误类型 00001
 | 
			
		||||
    // 通用错误类型 10001
 | 
			
		||||
    PARAMETER_VALIDATION_ERROR(10001, "参数不合法"),
 | 
			
		||||
    UNKNOWN_ERROR(10002, "未知错误"),
 | 
			
		||||
 | 
			
		||||
    // 10000开头为用户信息相关错误定义
 | 
			
		||||
    // 20000开头为用户信息相关错误定义
 | 
			
		||||
    USER_NOT_EXIST(20001, "用户不存在"),
 | 
			
		||||
    USER_LOGIN_FAILED(20002, "用户手机号或密码不正确");
 | 
			
		||||
    USER_LOGIN_FAILED(20002, "用户手机号或密码不正确"),
 | 
			
		||||
 | 
			
		||||
    // 30000开头为交易信息错误定义
 | 
			
		||||
    STOCK_NOT_ENOUGH(30001, "库存不足");
 | 
			
		||||
 | 
			
		||||
    private EmBusinessError(int errCode, String errMsg) {
 | 
			
		||||
        this.errCode = errCode;
 | 
			
		||||
 
 | 
			
		||||
@@ -14,4 +14,6 @@ public interface ItemService {
 | 
			
		||||
 | 
			
		||||
    // 商品详情浏览
 | 
			
		||||
    ItemModel getItemById(Integer id);
 | 
			
		||||
 | 
			
		||||
    boolean decreaseStock(Integer itemId, Integer amount) throws BusinessException;
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -0,0 +1,15 @@
 | 
			
		||||
package com.cxyxiaomo.flashsale.service;
 | 
			
		||||
 | 
			
		||||
import com.cxyxiaomo.flashsale.error.BusinessException;
 | 
			
		||||
import com.cxyxiaomo.flashsale.service.model.OrderModel;
 | 
			
		||||
 | 
			
		||||
public interface OrderService {
 | 
			
		||||
    /**
 | 
			
		||||
     *
 | 
			
		||||
     * @param userId 用户id
 | 
			
		||||
     * @param itemId 购买商品
 | 
			
		||||
     * @param amount 购买商品数量
 | 
			
		||||
     * @return
 | 
			
		||||
     */
 | 
			
		||||
    OrderModel createOrder(Integer userId, Integer itemId, Integer amount) throws BusinessException;
 | 
			
		||||
}
 | 
			
		||||
@@ -103,6 +103,19 @@ public class ItemServiceImpl implements ItemService {
 | 
			
		||||
        return itemModel;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    @Transactional
 | 
			
		||||
    public boolean decreaseStock(Integer itemId, Integer amount) throws BusinessException {
 | 
			
		||||
        int affectedRow = itemStockDOMapper.decreaseStock(itemId, amount);
 | 
			
		||||
        if (affectedRow > 0) {
 | 
			
		||||
            // 更新库存成功
 | 
			
		||||
            return true;
 | 
			
		||||
        } else {
 | 
			
		||||
            // 更新库存失败
 | 
			
		||||
            return false;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private ItemModel convertModelFromDataObject(ItemDO itemDO, ItemStockDO itemStockDO) {
 | 
			
		||||
        ItemModel itemModel = new ItemModel();
 | 
			
		||||
        BeanUtils.copyProperties(itemDO, itemModel);
 | 
			
		||||
 
 | 
			
		||||
@@ -0,0 +1,95 @@
 | 
			
		||||
package com.cxyxiaomo.flashsale.service.impl;
 | 
			
		||||
 | 
			
		||||
import com.cxyxiaomo.flashsale.dao.OrderDOMapper;
 | 
			
		||||
import com.cxyxiaomo.flashsale.dataobject.OrderDO;
 | 
			
		||||
import com.cxyxiaomo.flashsale.error.BusinessException;
 | 
			
		||||
import com.cxyxiaomo.flashsale.error.EmBusinessError;
 | 
			
		||||
import com.cxyxiaomo.flashsale.service.ItemService;
 | 
			
		||||
import com.cxyxiaomo.flashsale.service.OrderService;
 | 
			
		||||
import com.cxyxiaomo.flashsale.service.UserService;
 | 
			
		||||
import com.cxyxiaomo.flashsale.service.model.ItemModel;
 | 
			
		||||
import com.cxyxiaomo.flashsale.service.model.OrderModel;
 | 
			
		||||
import com.cxyxiaomo.flashsale.service.model.UserModel;
 | 
			
		||||
import org.springframework.beans.BeanUtils;
 | 
			
		||||
import org.springframework.beans.factory.annotation.Autowired;
 | 
			
		||||
import org.springframework.stereotype.Service;
 | 
			
		||||
import org.springframework.transaction.annotation.Transactional;
 | 
			
		||||
 | 
			
		||||
import java.math.BigDecimal;
 | 
			
		||||
 | 
			
		||||
@Service
 | 
			
		||||
public class OrderServiceImpl implements OrderService {
 | 
			
		||||
 | 
			
		||||
    @Autowired
 | 
			
		||||
    private ItemService itemService;
 | 
			
		||||
 | 
			
		||||
    @Autowired
 | 
			
		||||
    private UserService userService;
 | 
			
		||||
 | 
			
		||||
    @Autowired
 | 
			
		||||
    private OrderDOMapper orderDOMapper;
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    @Transactional
 | 
			
		||||
    public OrderModel createOrder(Integer userId, Integer itemId, Integer amount) throws BusinessException {
 | 
			
		||||
        // 1. 校验下单状态
 | 
			
		||||
        //  下单的商品是否存在;用户是否合法;购买数量是否正确
 | 
			
		||||
        ItemModel itemModel = itemService.getItemById(itemId);
 | 
			
		||||
        if (itemModel == null) {
 | 
			
		||||
            throw new BusinessException(EmBusinessError.PARAMETER_VALIDATION_ERROR, "商品信息不存在");
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        UserModel userModel = userService.getUserById(userId);
 | 
			
		||||
        if (userModel == null) {
 | 
			
		||||
            throw new BusinessException(EmBusinessError.PARAMETER_VALIDATION_ERROR, "用户信息不存在");
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (amount <= 0 || amount > 99) {
 | 
			
		||||
            throw new BusinessException(EmBusinessError.PARAMETER_VALIDATION_ERROR, "数量信息不正确");
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // 2. 落单减库存 / 支付减库存(有可能超卖)
 | 
			
		||||
        boolean result = itemService.decreaseStock(itemId, amount);
 | 
			
		||||
        if (!result) {
 | 
			
		||||
            throw new BusinessException(EmBusinessError.STOCK_NOT_ENOUGH);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // 3. 订单入库
 | 
			
		||||
        OrderModel orderModel = new OrderModel();
 | 
			
		||||
        orderModel.setUserId(userId);
 | 
			
		||||
        orderModel.setItemId(itemId);
 | 
			
		||||
        orderModel.setAmount(amount);
 | 
			
		||||
        orderModel.setItemPrice(itemModel.getPrice());
 | 
			
		||||
        orderModel.setOrderPrice(itemModel.getPrice().multiply(new BigDecimal(amount)));
 | 
			
		||||
 | 
			
		||||
        // 生成交易流水号,订单号
 | 
			
		||||
 | 
			
		||||
        OrderDO orderDO = convertFromOrderModel(orderModel);
 | 
			
		||||
        orderDOMapper.insertSelective(orderDO);
 | 
			
		||||
 | 
			
		||||
        // 4. 返回前端
 | 
			
		||||
 | 
			
		||||
        return null;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private OrderDO convertFromOrderModel(OrderModel orderModel) {
 | 
			
		||||
        if (orderModel == null) {
 | 
			
		||||
            return null;
 | 
			
		||||
        }
 | 
			
		||||
        OrderDO orderDO = new OrderDO();
 | 
			
		||||
        BeanUtils.copyProperties(orderModel, orderDO);
 | 
			
		||||
 | 
			
		||||
        return orderDO;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // 生成交易流水号,订单号
 | 
			
		||||
    private String generateOderNo(){
 | 
			
		||||
        // 订单号为16位
 | 
			
		||||
        // 前8位为时间信息(年月日)
 | 
			
		||||
 | 
			
		||||
        // 中间6位为自增序列
 | 
			
		||||
 | 
			
		||||
        // 最后2位为分库分表位
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -114,4 +114,10 @@
 | 
			
		||||
    from item_stock
 | 
			
		||||
    where item_id = #{itemId,jdbcType=INTEGER}
 | 
			
		||||
  </select>
 | 
			
		||||
  <update id="decreaseStock">
 | 
			
		||||
    update item_stock
 | 
			
		||||
    set stock = stock - #{amount},
 | 
			
		||||
    item_id = #{itemId}
 | 
			
		||||
    where item_id = #{itemId} and stock >= #{amount}
 | 
			
		||||
  </update>
 | 
			
		||||
</mapper>
 | 
			
		||||
		Reference in New Issue
	
	Block a user