jianzhangg

https://juejin.cn/post/7460418134312255514

今天写代码突发一个诡异的 bug,代码逻辑大概如下。


java 代码解读
复制代码
// 1. 新增退款单记录boolean save = shopOrderRefundService.save(shopOrderRefundAdd);

// 2. 调用京东退款MiniappRefundResponse response = jdOrderOpenApiService.miniappRefund(...);
if (response.isSuccess()) {
    shopOrderRefundAdd.setStatus(ShopOrderRefundStatusEnum.SYNC_FAIL.getDatabaseCode());
    boolean update = shopOrderRefundService.updateByIdAndStatus(shopOrderRefundAdd);
    //返回失败    ...
}

// 3. 更新退款单状态调用成功shopOrderRefundAdd.setStatus(ShopOrderRefundStatusEnum.JD1001.getDatabaseCode());
boolean update = shopOrderRefundService.updateByIdAndStatus(shopOrderRefundAdd);
...

先生成退款单入库,再调京东接口,根据接口返回值再修改退款单状态。

问题是第三步修改的时候,有时成功有时失败。

本地跑了下,跟事物没关系。


java 代码解读
复制代码
Creating a new SqlSessionSqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@af21da9] was not registered for synchronization because synchronization is not active
JDBC Connection [org.apache.shardingsphere.driver.jdbc.core.connection.ShardingSphereConnection@546d31d3] will not be managed by Spring
Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@af21da9]

拉同事过来一起看,发现修改的代码有问题。


java 代码解读
复制代码
public boolean updateByIdAndStatus(ShopOrderRefund shopOrderRefund, Integer status) {
    DateTime date = DateUtil.date();
    return update(shopOrderRefund,new LambdaUpdateWrapper<ShopOrderRefund>()
            .eq(ShopOrderRefund::getOrderNo,shopOrderRefund.getOrderNo())
            .eq(ShopOrderRefund::getStatus,status)
            .between(ShopOrderRefund::getCreateAt, DateUtil.offsetMonth(date, -2), date)
    );
}

copy 代码的时候忘把时间范围去掉,用单号查就没问题了。

但就算有时间范围,创建的时候肯定在修改前,为什么还是查不到呢?

又跑了几遍发现时间插入的问题。

注意看时间的毫秒,如果传入的SQL带毫秒,MySQL在入库的时候自动四舍五入了,这导致本来是 07.599 秒的数据变成了 08 秒。

但也不对,后面就算是 07.699,如果转成 08 也能查到。

我把更新 SQL 的查询部分单独拎出来看。