小程序开发-服务端
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 

5.9 KiB

订单数据库字段缺失默认值修复指南

问题描述

在提交订单时遇到以下数据库错误:

{"code":1,"message":"\n### Error updating database.  Cause: java.sql.SQLException: Field 'pay_price' doesn't have a default value\n### The error may exist in com/gxwebsoft/shop/mapper/ShopOrderMapper.java (best guess)\n### The error may involve com.gxwebsoft.shop.mapper.ShopOrderMapper.insert-Inline\n### The error occurred while setting parameters\n### SQL: INSERT INTO shop_order (order_no, delivery_type, address_id, total_price, price, pay_user_id, pay_type, pay_status, user_id, comments, tenant_id) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, 10550)\n### Cause: java.sql.SQLException: Field 'pay_price' doesn't have a default value\n; Field 'pay_price' doesn't have a default value; nested exception is java.sql.SQLException: Field 'pay_price' doesn't have a default value"}

根本原因

数据库表 shop_order 中的 pay_price 字段没有设置默认值,而在插入订单记录时没有为该字段提供值,导致 SQL 插入失败。

解决方案

1. 修改 buildShopOrder 方法

OrderBusinessService.buildShopOrder() 方法中添加了所有必需字段的默认值设置:

// 设置价格相关字段(解决数据库字段没有默认值的问题)
if (shopOrder.getPayPrice() == null) {
    shopOrder.setPayPrice(shopOrder.getTotalPrice()); // 实际付款默认等于订单总额
}

if (shopOrder.getPrice() == null) {
    shopOrder.setPrice(shopOrder.getTotalPrice()); // 用于统计的价格默认等于订单总额
}

if (shopOrder.getReducePrice() == null) {
    shopOrder.setReducePrice(BigDecimal.ZERO); // 减少金额默认为0
}

if (shopOrder.getMoney() == null) {
    shopOrder.setMoney(shopOrder.getTotalPrice()); // 用于积分赠送的价格默认等于订单总额
}

// 设置默认状态
shopOrder.setPayStatus(false); // 未付款
shopOrder.setOrderStatus(0); // 未使用
shopOrder.setDeliveryStatus(10); // 未发货
shopOrder.setIsInvoice(0); // 未开发票
shopOrder.setIsSettled(0); // 未结算
shopOrder.setCheckBill(0); // 未对账
shopOrder.setVersion(0); // 当前版本

// 设置默认支付类型(如果没有指定)
if (shopOrder.getPayType() == null) {
    shopOrder.setPayType(1); // 默认微信支付
}

2. 修改 applyBusinessRules 方法

确保测试账号逻辑也正确设置所有相关字段:

// 测试账号处理
if (orderConfig.isTestAccount(loginUser.getPhone())) {
    BigDecimal testAmount = orderConfig.getTestAccount().getTestPayAmount();
    shopOrder.setPrice(testAmount);
    shopOrder.setTotalPrice(testAmount);
    shopOrder.setPayPrice(testAmount); // 确保实际付款也设置为测试金额
    shopOrder.setMoney(testAmount); // 确保积分计算金额也设置为测试金额
    log.info("应用测试账号规则,用户:{},测试金额:{}", loginUser.getPhone(), testAmount);
}

修复的字段列表

字段名 默认值 说明
payPrice totalPrice 实际付款金额,默认等于订单总额
price totalPrice 用于统计的价格,默认等于订单总额
reducePrice BigDecimal.ZERO 减少的金额(优惠券、折扣等)
money totalPrice 用于积分赠送的价格
payStatus false 支付状态,默认未付款
orderStatus 0 订单状态,默认未使用
deliveryStatus 10 发货状态,默认未发货
isInvoice 0 发票状态,默认未开发票
isSettled 0 结算状态,默认未结算
checkBill 0 对账状态,默认未对账
version 0 系统版本,默认当前版本
payType 1 支付类型,默认微信支付

测试验证

创建了专门的测试用例 testBuildShopOrder_RequiredFields 来验证所有必需字段都正确设置:

@Test
void testBuildShopOrder_RequiredFields() throws Exception {
    // 验证必需字段都已设置
    assertNotNull(result.getPayPrice(), "payPrice 不能为空");
    assertNotNull(result.getPrice(), "price 不能为空");
    assertNotNull(result.getReducePrice(), "reducePrice 不能为空");
    assertNotNull(result.getMoney(), "money 不能为空");
    // ... 其他字段验证
    
    // 验证默认值
    assertEquals(testRequest.getTotalPrice(), result.getPayPrice());
    assertEquals(testRequest.getTotalPrice(), result.getPrice());
    assertEquals(BigDecimal.ZERO, result.getReducePrice());
    // ... 其他默认值验证
}

业务逻辑说明

价格字段关系

  1. totalPrice: 订单总额,由商品价格计算得出
  2. payPrice: 实际付款金额,通常等于 totalPrice,但可能因优惠而不同
  3. price: 用于统计的价格,通常等于 totalPrice
  4. money: 用于积分赠送计算的价格
  5. reducePrice: 优惠减免的金额(优惠券、VIP折扣等)

计算公式

payPrice = totalPrice - reducePrice

在没有优惠的情况下:

payPrice = totalPrice
reducePrice = 0

影响范围

这个修复解决了以下问题:

  1. 数据库插入错误: 解决了 pay_price 等字段缺少默认值的问题
  2. 订单状态完整性: 确保所有状态字段都有正确的初始值
  3. 价格计算一致性: 保证各个价格字段的逻辑关系正确
  4. 测试账号兼容性: 确保测试账号逻辑正常工作

注意事项

  1. 向后兼容: 修改保持了向后兼容性,不会影响现有功能
  2. 数据完整性: 所有必需字段都有合理的默认值
  3. 业务逻辑: 默认值符合业务逻辑,不会产生异常数据
  4. 测试覆盖: 有完整的测试用例覆盖修改的功能

总结

通过在 buildShopOrder 方法中添加完整的字段默认值设置,成功解决了订单提交时的数据库字段缺失问题。这个修复不仅解决了当前的错误,还提高了系统的健壮性,确保订单数据的完整性和一致性。