1 什么是 Mybatis 灵活SQL
假设你经常使用过 JDBC 或其它相似的框架,你应该能了解依据不同条件拼接 SQL 语句有多痛苦,例如拼接时要确保不能遗记参与必要的空格,还要留意去掉列表最后一个列名的逗号。
Mybatis 借助性能弱小 OGNL 表白式,可以依据参数条件,灵活生成口头 SQL 。
经常使用灵活 SQL 最经常出现情形是依据条件蕴含 where 子句的一局部。
这条语句提供了可选的查问博客文章列表 ,假设不传入 “title”,那么一切处于 “ACTIVE” 形态的 博客都会前往。
假设传入了 “title” 参数,那么就会对 “title” 一列启动含糊查找并前往对应的 BLOG 结果。
假设宿愿经过 “title” 和 “author” 两个参数都可以搜查,只须要参与另一个条件即可,见下图:
咱们也可以经常使用 where 标签,该标签只会在子元素前往任何内容的状况下才拔出 “WHERE” 子句。而且,若子句的扫尾为 “AND” 或 “OR”,where 标签也会将它们去除。
Mybatis 还允许 choose (when, otherwise)、trim (where, set)、foreach 等其余的灵活标签,这里就不逐一赘述了。
2 人生第一次性线上OOM意外
我曾服务一家电商公司的用户核心,用户核心提供用户注册,查问,修正等基础性能 。
那个时刻 Dubbo 等 RPC 框架并没有开源,一切的服务都以 HTTP 接口方式提供,数据传输格局是 XML 。
由于写接口十分吃力,所认为了接口复用,我写了一个通用接口 getUserByConditions ,该接口允许经过 「用户名」、「昵称」、「手机号」、「用户编号」这三个查问用户基本消息。
经常使用的是 ibatis (mybatis 的前身), SQLMap 见下图 。
当构建灵活 SQL 查问时,条件通常会追加到子句后,而以扫尾,可以轻松地经常使用追加其余条件。
用户核心在上线后,居然每隔三四个小时就出现了内存溢出疑问 ,经过经过和 DBA 沟通,发现高频次出现全表查用户表,口头 SQL 变成 :
检查日志后,发现前端传递的参数出现了空字符串,笔者在代码中并没有做参数校验,所以才出现全表查问 ,过后用户表的数据是 1000多万 ,页面调用几次,用户核心服务就 OOM 了。
最终处置疑问的方式很繁难,后端在接纳参数时,做了参数校验。
意外只管处置了,但对我的影响不时间断至今。我依然记切过后站在运维同窗旁边,不时的看他调整 JVM 参数 ,重启服务的画面,自己那个时刻真的是羞愧难当,心中发誓:相对无法以出现相似的意外。
关于灵活 SQL ,我的编程思想也阅历了如下三个阶段 :
3 前后端参数校验
为了优化开发效率,咱们人为的将系统分为前端、后端,区分由两拨不同的人员开发 ,经常出现系统疑问时,两拨人都十分不信服,相互指摘。
要想系统强健,前后端应该同时做接口参数校验 (后端必需做参数校验),当大家都遵照这个规约时,出现系统疑问的危险大大缩小。
1)前端校验
前端校验,关键是为了提高用户体验,例如用户输入一个邮箱地址,要校验这个邮箱地址能否合法,没有必要发送到服务端启动校验,间接在前端用 js 启动校验即可。
然而大家须要明白的是,前端校验无法替代后端校验,前端校验可以有效的提高用户体验,然而无法确保数据完整性,由于在 B/S 架构中,用户可以繁难的拿到恳求地址,而后间接发送恳求,传递合法参数。
2)后端校验
后端必需做参数校验,后端必需做参数校验,后端必需做参数校验,关键的事件表白三次。
数据在网络传输环节中有或许被窜改了,或许数据不满足业务需求,假设不做后端参数校验,则有或许造成系统意外,或许业务出现严重意外。
比如在 SpringBoot 名目中,咱们可以经常使用hibernate-validator启动参数校验 。
POST、PUT 恳求普通会经常使用 requestBody 传递参数,这种状况下,后端经常使用 DTO 对象启动接纳。
只需给 DTO 对象加上 @Validated 注解就能成功智能参数校验。比如,有一个保留 User 的接口,要求 userName 长度是 2-10,account 和 password 字段长度
是 6-20。
在 DTO 字段上申明解放注解:
在方法参数上申明校验注解:
只管,咱们可以经常使用接口校验,可以保障灵活 SQL 的参数正确,然而假设咱们仅仅只是复用 SQLMap (Dao 方法)时,也有或许由于调用方传递参数失误,造成非预期的疑问。
当然,咱们也可以经常使用 Mybatis 阻拦器从基本过去处置,然而我想这样会放大系统的复杂度。于是,我思索了了另外一点:复用和公用要做平衡。
4 复用和公用要做平衡
我过后写的那个接口 getUserByConditions ,是允许四种不同参数的查问,雷同也是为了省期间,快点出活。
起初,随着我上班阅历的日益丰盛,我的编程习气也缓缓出现了扭转,关于业务需求明白的场景,我更多的偏差于将通用接口拆分红公用接口。
比如 getUserByConditions 可以拆分红如下四个接口 ,
比如依照用户 ID 查问用户消息 , SQLMAP 就简化为:
经过这样的拆分,咱们的接口设计愈加细粒度,也更容易保养 , 同时也可以规避 where 1 =1 发生的不确定性(只管我做了后端校验,依然存在不确定性)。
有的同窗会有不懂:假设拆分得太细,会不会参与我编写接口和 SQLMap 的上班量 ?
笔者的思绪是:定制自己的代码生成器,将生成的 SQLMap 、Mapper 保障更细的颗粒度。
5 进攻性编程看法
笔者刚入行的时刻,只是机械性的成功义务,并没有思索代码前面的资源占用,以及有没有或许发生顽劣的影响。
随着见识更多的系统,学习开源名目,笔者缓缓造就了一种习气:
其实,这和玩游戏差不多 ,在玩游戏的时,咱们经常说一个词,那就是看法。
上图,后裔跟墨子在压对面马可蔡文姬,看到小地图中路铠跟小乔的视线,方向是往下路来的,这时刻咱们就失掉了一个消息。
知道对面的人要来抓,或许是协防,这种状况咱们只要两团体,其余的队友都不在,只能选用避战,强打只会损失两名“大将”。
经过小地图的消息,并且想出应答方法,就是叫做“猜想看法”。
编程也是一样的,咱们思索代码或许发生的系统资源占用,以及或许存在的危险,并做好进攻性编程,就是编程的看法。
6 写到最后
人生第一次性线上 OOM 意外,因我在经常使用 Mybatis 灵活 SQL 时,没有做后端校验而出现,形成了比拟坏的影响。
在前面的职业生涯外面,为了规避消费环境的意外,我试着打磨自己的编程思想,比如做好后端校验、平衡好复用和公用接口、造就进攻性编程的看法。