乐趣区

关于后端:一些在代码中踩过的坑从来没遇到过的估计已经不是大头兵了

前言
在咱们日常 coding 中,很多时候咱们都是把接口代码全副写完再进行测试,在咱们查看代码的时候,经常很有信念查看了多遍当前,感觉本人的代码必定没啥问题,逻辑很清晰、排版很参差、公共办法抽的很好,很有信念的去调本人的接口,不料动不动一会 500、一会 400,就差报 250~,其实咱们经常的我认为,只是我认为,执行后果会教你做人,事实证明代码不须要只是看着难看的,还是须要看执行后果的,上面我分享一些日常会踩到坑的中央
八大常见 bug
Top1 申请参数为空
经常听到,数据库明明有数据呀,我把 sql 粘进去再 mysql 执行也有数据呀,为什么我用 mybatis 执行 sql 就没数据呢。

POST 申请,如参数为字符串,申请到后端接口只能有一个后果,那就是 parameter 参数为 NULL,影响行数也 0,POST 申请须要联合 RequestBody 应用,所以 POST 申请的入参是放到 body 外面的。
Top2 StringUtils.isEmpty 判断对象为空
User user = User(new LambdaQueryWrapper<User>()

    .eq(User::getUserId, userId)

if (!StringUtils.isEmpty(user))
复制代码
乍一看没啥问题,代码也没报错,判断 user 不为空,然而执行的时候往往就会有问题。
对象签名对于个别的属性解决代码很有用,这些代码通常解决字符串,但通常必须遍历对象,因为属性也可能是根本值对象。
Note: If the object is typed to String upfront, prefer hasLength(String) or hasText(String) instead.
Params:
str – the candidate object (possibly a String)
Since:
3.2.1
See Also:
hasLength(String), hasText(String)
public static boolean isEmpty(@Nullable Object str) {

return (str == null || "".equals(str));

}

复制代码
看源码的解释,通常是解决字符串,判断对象须要重写 isEmpty 办法。
Top3 sql if 函数判断
if(p.transport_fee =1,p.payable_amount,s.actual_goods_number * p.goods_price) as payableAmount,
复制代码
失常状况下如果 transport_fee =1 则会取 p.payable_amount 字段,反之则会取前面的运算后果,乍一看又没啥故障。

然而 如果这个字段是 NULL,那么就 BBQ 了,mysql if 函数判断就不会判断到字段为 NULL 的数据。所以最好在创立这种须要逻辑判断的字段,设置默认值。
Top4 Mybatis plus lambda 表达式 AND 和 OR 连用
其实咱们 sql 想要的成果是这样
select
<include refid=”baseColumnList”/>
from slaughter_batch_statement
where
enable = 1

and  (slaughter_statement_no

=#{dto.slaughterStatementNo
} or slaughter_statement_no is null)
复制代码
LambdaQueryWrapper 查问谬误用法:
SlaughterBatchStatement slaughterBatchStatement = slaughterBatchStatementMapper.selectOne(new LambdaQueryWrapper<SlaughterBatchStatement>().

eq(SlaughterBatchStatement::getSlaughterStatementNo, slaughterStatementNo).or().eq(SlaughterBatchStatement::getBatchNo,slaughterStatementNo));

复制代码
or().eq() 的用法会在 sql,and 条件后追加 or,而不能
(supplier_bill_statement_no =‘xxxxxxx’or supplier_bill_statement_no is null) 像这样用括号括起来,括号括起来和不括起来的条件判断齐全不一样。
LambdaQueryWrapper or 正确用法:
SlaughterBatchStatement slaughterBatchStatement = slaughterBatchStatementMapper.selectOne(new LambdaQueryWrapper<SlaughterBatchStatement>().

    eq(SlaughterBatchStatement::getEnable, 1).and
            (item -> item.eq(SlaughterBatchStatement::getSlaughterStatementNo, "xxxxx")
                    .or().eq(SlaughterBatchStatement::getSlaughterStatementNo, null)));

复制代码
Top5 BigDecimal 保留两位小数
有时候做金额计算的时候,应用 BigDecimal 常常会在计算后保留两位小数。
BigDecimal receivableAmountNum = receivableFeeAmountNum.add(slaughterReceivableAmountNum).setScale(2, RoundingMode./HALF_UP/);
复制代码
你认为光代码设置保留两位小数就行了么,数据库对字段的设置也是须要加两位小数限度的。

如果你不设置,那么保留到库外面的数据仍旧是四舍五入后的整数。
Top6 Spring 中一个类调用另一个类 Null 指针
新建一个类,而后在另一个类去调用,创立了一个类,定义了办法。

谬误调用形式:这是空指针的罪魁祸首

正确的调用形式:

Spring 中间接 new 进去的对象无奈通过 @Autowired 的形式注入到 spring 的 Bean 容器外面。
Top7 Bean. copyProperties 引发的问题
在开发的过程中,遇到 DTO 和 VO 之间的转换,为了防止写很多的 get、set,通常会应用 Bean. copyProperties 对对象进行赋值转换。
SlaughterBatchStatementResVO slaughterBatchStatementResVO = new SlaughterBatchStatementResVO();
SlaughterBatchStatement slaughterBatchStatement = slaughterBatchStatementMapper.selectOne(new LambdaQueryWrapper<SlaughterBatchStatement>().

    eq(SlaughterBatchStatement::getSlaughterStatementNo, slaughterUpdateReqDTO.getSlaughterStatementNo()));

// 对象进行 copy
BeanCopyUtil.copyProperties(slaughterBatchStatement, slaughterBatchStatementResVO);

复制代码
BeanCopyUtil.copyProperties 这里的 copy 属于浅拷贝,两个对象都指向同一个指针,所以在对其中一个对象属性进行批改时,因为指针都是一样,那么另外一个对象的属性也会更改,就会呈现一些问题。
当然 Bean 的 copy 还有另外一种形式就是深拷贝,通过 new 新的对象进行 copy
List<ReceivableFeeVO> receivableFeeResList = BeanCopyUtil.copyListProperties(slaughterUpdateReqDTO.getReceivableFees(), ReceivableFeeVO::new);
复制代码
能够通过继承 BeanUtils 重写 Bean 拷贝的工具类实现

Top8 List.contains Interger 无奈匹配
@Data
public class SlaughterBatchExportRequestDTO {


private List<String> slaughterBatchExportType;

}

if (slaughterBatchExportRequestDTO.getSlaughterBatchExportType().contains(2)) {

// …
}
复制代码

有时候一不留神就手抖写错了,contains 的入参是一个 Object 类型,所以入参数是任何类型都不报错,然而能不能匹配到又是另外一回事了。
List 汇合去匹配 int 类型是否存在,那后果可想而已永远不会进 if 判断。
总结
刚工作的时候常常会因为本人的大意,呈现一些比拟低级的 Bug,现在曾经多少混成老油条了,所以去写更加高级的 Bug 了,总而言之写代码不光要逻辑思路正确,最要害的我认为还是仔细,重复的 review 本人的代码,并且进行自测,如果还有更加常见的 bug 的欢送评论区留言,踩坑踩的多了,填坑填的多了,缓缓就变成了路~

退出移动版