背景

前天晚上,我们部门后端技术leader(我们叫他侃哥)请我们后端组出去吃了个饭,其他暂且不提,在聊天中聊到了现在开发的一个项目中遇到的一个小问题,我觉得对我来说确实是一个坑点,所以在这记录一下。

事情的起因是这样的,我们现在做的项目是一个面向企业的toB端项目,因此对时间卡的比较紧。但是因为这是我们团队的第一次合作,出了不少岔子,bug改了好长时间,交付日期一延再延,我们总经理(贺总)有点遭不住了。

因为贺总也是技术出身,对Java技术也有所理解,因此在晨会上为了找出问题直接让我们演示代码,然后看到了一坨离谱的代码(没错我写的)。

这坨代码我当时写的时候没写注释(大坑,后面新项目长教训了),反正就是完成一个查询的逻辑。但是我们的数据库设计的特别复杂,为了查到这个结果需要联查四五张表才能把所有关联字段翻译出来。

作为一个还没毕业,实习刚入职两个月,以前做php,才学了两天Spring(会Java,之前手撸过MVC框架,所以学起来很快)就开始做Spring Boot的辣鸡,面对不用写SQL的持久层框架MyBatis Plus,觉得这东西简直是太方便了,于是乎,我这坨联查的逻辑就变成了。。。

先查带信息的全部子表,存成map,再一个个查关联关系表,遍历关系表从map里面取出来放到Entity里面去(当时我还觉得我贼聪明来着

然后不出意外的,被贺总一顿骂(不过侃哥对我真不错,没把我直接捅出去)。贺总的出发点是可维护性和健壮性(因为每个子逻辑都需要判断一次Null)。

然后我们在晚上吃饭的时候又提到了这件事情(说了一大顿废话终于讲到重点了)

讨论

我的一个同事认为,如果联查的时候使用左右查询,查询的时候会多次重复地遍历去匹配结果,而在Java中直接用Map匹配的话就会快得多得多,因此他认为在大量联查的情况下用MyBatis Plus的Mapper方法要比写XML的SQL快。

这里我觉得也是蛮有道理的,毕竟映射结构比遍历要方便的多也快的多。这个时候侃哥提出了一个问题,就是数据库连接的问题。如果多次单表查询,每次都需要建立连接,那么等待连接的时间将会更长。

这时我的那位同事说持久层的连接是连接池维护的,所以建立连接的时候不会消耗大量的额外时间。然而侃哥说,他的意思是,如果在并发增高的情况下(因为在设计上这个项目的并发并不高,所以大家也没有去特别关注高并发处理的问题),如果连接池满,就需要阻塞等待,如果分开查询,整个事务都会被阻塞掉,这样造成的风险和延迟就会更高。因此,用单SQL语句用执行时间换安全性和健壮性要更值得一些。

思考了一下,确实是这样。其实这种问题稍微思考一下就能想得出来,但是就是贪图方便,说白了还是懒,大量的使用MyBatis Plus反复的单表查写起来确实容易,但是也应该事先想到他内在的隐患,所以还是有很多东西需要学习,还有很多经验需要积累。

最后顺带一提,用注解的方式(我唯一一个手写的SQL就是注解写的)写语句也不可取,可读性太差了,时间长了连自己都看不懂了。因此,为了安全性和健壮性还有可维护性,最好还是要将大量的联查行为写成SQL放到XML里面。

本篇内容为原创内容,采用CC BY-NC-SA 4.0协议许可
2021-08-25 18:37
UtopiaXC
于北京


尽管如此,世界依旧美丽