关于jfinal中findFirst方法的健壮性建议

最近带一个新人,犯了一个比较低级的小错误造成功能崩溃:

1、使用jfinal的sql管理,为了方便拼接sql,使用了 where 1 = 1,然后判断参数是否存在追加 and xxx = xxx

2、刚好某句代码未将该有的参数传递过去;

3、刚好测试没有测出来;

4、刚好单表数据量较大,sql表关联较多,逻辑稍微复杂;

结果:

造成了findFirst执行了find后返回大量数据,最终内存消耗太高造成程序崩溃无响应。


建议:在findFirst中使用paginate分页查询,默认查询一页,每页1条数据,而不使用find进行查询list,避免此类问题发生。

评论区

JFinal

2019-02-28 11:44

findFirst 方法的注释中已经明确说明了要根据不同的数据库添加不同的限定,例如 mysql 是添加 limit 1:
select * from xxx where ... limit 1

这个设计在 8 年前是这么来考虑的:
1:不同的数据库由于限定方式不同所以 Dialect 中没有帮你加 limit 1,而是留给用户自己加

2:后来过了几年有人提出这个需求,希望 jfinal 自动加 limit 1,但这时考虑到会影响已经加过 limit 1的用户,也就没再动这里。虽然可以通过判断 sql 中是否存在 limit 来决定要不要加 limit,但代码不太优雅,也就作罢

3:不同的数据库是加不同的限定,如 Sql Server 是加 select top 1,所以想加也不太方便,担心会干扰现有 sql,不如用户自己加来得方便

4:退一步讲,findFirst 查询一般用的查询条件是 id 值,出现问题的情况并不多

总得来说还是该进一步处理一下,jfinal 3.7 考虑改进

jounzhang

2019-02-28 11:58

jounzhang

2019-02-28 11:59

@JFinal 好的,正常情况下确实不会出现问题,手动加麻烦,我们一般都不会加

JFinal

2019-02-28 12:33

@jounzhang 主要还是历史原因引起的,jfinal 的这个设计是在 2011 年完成的,一直没有动过

findFirst 一般是在 id 上使用 where 条件,而 id 是唯一的,所以只会返回一条数据,由于 id 是自动被索引过的,性能也是最好的

xialinlin

2019-02-28 16:59

findFirst 一般只会用于ID查询,只会有一条的情况下,其他情况肯定自己处理

杜福忠

2019-03-01 00:45

我觉得,如果自己的项目需要这个功能了话又没有历史包袱,Model直接在Base层重写一下就可以了,DbPro的话com.jfinal.plugin.activerecord.IDbProFactory中写的activeRecordPlugin.setDbProFactory(new MyDbProFactory()) 里的findFirst方法也是一样的重写一下就OK了

热门反馈

扫码入社