我们提供安全,免费的手游软件下载!

安卓手机游戏下载_安卓手机软件下载_安卓手机应用免费下载-先锋下载

当前位置: 主页 > 软件教程 > 软件教程

关于 Mybatis +「where 1 = 1」编程模式的深入思考

来源:网络 更新时间:2024-06-03 04:31:37

在本文中,我想和大家分享一个经常应用的编程模式:Mybatis +「where 1 = 1」。这个模式在开发中经常使用,然而我个人却因为这种模式经历过一次线上事故,让我对它留下了深刻印象。

这几天,当我在调试业务代码时,又一次遇到了类似的问题。因此,我认为有必要和大家分享我的经验教训。

1. OOM 事故

在过去,我曾服务一家电商公司的用户中心,该用户中心提供用户注册、查询、修改等基础功能。其中有一个名为 getUserByConditions 的接口,它支持通过 「用户名」、「昵称」、「手机号」和「用户编号」来查询用户的基本信息。

我们使用的是 ibatis(mybatis 的前身),SQLMap 如上图所示。在构建动态 SQL 查询时,通常会将条件追加到 WHERE 子句后。而使用 WHERE 1 = 1 开头,可以轻松地使用 AND 来追加其他条件。

但在用户中心上线后,每隔三四个小时就会发生内存溢出问题。通过与 DBA 沟通,发现高频次出现全表查询用户表的情况,执行的 SQL 变成了:

查看日志后,我们发现前端传递的参数中存在空字符串。由于我在代码中并没有进行参数校验,因此导致了全表查询。当时,用户表的数据量达到了1000万,只需几次这样的调用,用户中心服务就会发生内存溢出。我随后在用户中心服务中添加了接口参数校验,即验证「用户名」、「昵称」、「手机号」和「用户编号」。自此之后,我们再也没有遇到过类似的问题。

2. 思维进化

1)前后端同时做接口参数校验

为了提升开发效率,我们人为地将系统分为前端和后端,分别由两组不同的人员开发。然而,通常情况下当系统出现问题时,两组人员都非常不服气,相互指责。

有时,我会觉得很搞笑,因为这本质上是个规约问题。

要使系统更加健壮,前后端应该同时进行接口参数校验。只有在大家都遵循这个规约的时候,系统出现问题的风险才会大大降低。

2)复用和专用要做平衡

我编写的接口 getUserByConditions,支持四种不同参数的查询。然而,由于代码不够严谨,导致系统出现了 OOM 问题。

在业务非常明确的场景下,我们其实可以将复用接口拆分为四个更细粒度的接口:

  • 按照用户 ID 查询用户信息
  • 按照用户昵称查询用户信息
  • 按照手机号查询用户信息
  • 按照用户名查询用户信息

例如,按照用户 ID 查询用户信息的 SQLMap 如下所示:

通过这种拆分,我们的接口设计变得更加细粒度,也更容易维护,同时也可以规避由"where 1 = 1"产生的问题。

有些同学可能会有疑问:假如拆分得太细,会不会增加接口和 SQLMap 的编写工作量?

我的看法是:我们可以通过代码生成器动态生成,这是可以做到的,只需要进行轻微的定制。

3)编写代码时,需要考虑资源占用量,做好预防性编程

我刚入行的时候,只是机械性地完成任务,并没有考虑代码后面可能占用的资源,也没有思考其可能产生的恶劣影响。

随着更多的系统经验和对开源项目的学习,我慢慢养成了一种习惯:

  • 这段代码会占用多少系统资源?
  • 如何规避风险,做好预防性编程。

其实,这和玩游戏差不多。在玩游戏的时候,我们经常说一个词,那就是 「意识」

上图中,后裔跟墨子在压对面马可蔡文姬,通过小地图中路铠跟小乔的视野,我们可以判断他们是往下路来的。这时候我们就得到了一个信息。

知道对面的人要来抓,或者是协防,这种情况我们只有两个人,其他的队友都不在,只能选择避战,强打只会损失两名“大将”。

通过小地图的信息,并且设想出应对方法,这就是 「猜测意识」

编程也一样,我们需要思考代码可能产生的系统资源占用,以及可能存在的风险,并采取预防性编程来对抗这种情况,这就是 编程的意识

4. 写到最后

在使用 Mybatis +「where 1 = 1」编程模式时,我们需要注意以下三点:

  1. 前后端需同时进行接口参数校验;
  2. 在条件允许的情况下,复用和专用需做平衡,将复用 SQLMap 拆分成更细粒度的 SQLMap;
  3. 在编写代码时需要考虑资源占用量,进行预防性编程。

文章片段推荐:

生命就是这样一个过程,一个不断超越自身局限的过程,这就是命运,任何人都是一样,在这过程中我们遭遇痛苦、超越局限、从而感受幸福。

所以一切人都是平等的,我们毫不特殊。

--- 史铁生


如果我的文章对你有所帮助,请帮忙 点赞、在看、转发 一下。你的支持会激励我输出更高质量的文章,非常感谢!