动态SQL执行分页查询出错

错误信息:java.lang.RuntimeException: com.jfinal.plugin.activerecord.ActiveRecordException: com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'limit 0, 20' at line 5


代码:

public Page<Record> getUnreadList(String uid, Integer pageNum){
    SqlPara sqlPara = dbo().getSqlPara("getUnreadList", Kv.by("uid", uid));
    return dbo().paginate(pageNum, 20, sqlPara);
}


然而,换成不分页的方式就没有问题:

public List<Record> getList(String uid){
    SqlPara sqlPara = dbo().getSqlPara("getUnreadList", Kv.by("uid", uid));
    return dbo().find(sqlPara);
}


其中的 dbo() 是父类提供的 Db.use(...) 对象


原SQL:

#sql("getUnreadList")
    SELECT rec.id, rec.reciveId, rec.reciveName, sub.mtype, sub.content, sub.senderId, sub.senderName, sub.cdate
    FROM msg_recive rec
    INNER JOIN msg_subject sub on sub.id = rec.subjectId
    WHERE rec.reciveId = #para(uid) and rec.readed = 0;
#end


看到老大的回复,将SQL修改成带括号的形式:

#sql("getUnreadList")
    SELECT * FROM
    (
        SELECT rec.id, rec.reciveId, rec.reciveName, sub.mtype, sub.content, sub.senderId, sub.senderName, sub.cdate
        FROM msg_recive rec
        INNER JOIN msg_subject sub on sub.id = rec.subjectId
        WHERE rec.reciveId = #para(uid) and rec.readed = 0
    ) temp;
#end


之后还是出错,错误提示跟上面的一样

把整个语句复制到数据库执行没问题

评论区

JFinal

2018-09-19 00:44

取决于你的 sql 在分页方法之下是不是正确,看一下文档 paginate 的第 5 小节《常见问题解决》:
http://www.jfinal.com/doc/5-6

netwild

2018-09-19 09:06

@JFinal 已经把SQL语句补充到问题里了~!
按照文档里的说法,原来应该是表连接的问题
把原SQL用括号包起来还是出错,这地方写起来真挺伤神的~!
还请老大看看怎么回事

netwild

2018-09-19 09:17

@JFinal 找到问题原因了!
原来是SQL最后那个分号闹的!
最后处理分页的时候,要在语句最后面再连接“limit 0, 20”

netwild

2018-09-19 09:19

以前留下来的习惯,总爱在sql结尾加个分号
希望别人看到这个能避免一下吧
也希望老大能优化一下这个地方,能自动把原SQL结尾的分号删除

Don小浩

2018-09-19 11:45

@netwild 老大不可能什么事都帮助解决 大方向上解决 细节上的程度跟你的实现和需求挂钩的就不好解决了,就像mybatis里面写sql语句也是建议不要加分号,你不能要求mybatis什么都改了,如果问题能解决的话 就先这样做呗 实在想要自己的那种 jfinal都是直接自己实现的

netwild

2018-09-19 13:13

@Don小浩 感谢老兄的回复,但我并不认可你的逻辑!

我说的“希望老大能优化一下这个地方,能自动把原SQL结尾的分号删除”这句话,不是让老大帮我解决问题,还没那么大脸,我是希望jf能更贴心,更好用。
我现在已经知道这个坑了,一个全局替换就能搞定的小事,真不需要老大帮忙。
但肯定还有很多不知道这个坑的朋友,不代表他们能平安无事的绕过去。
所以我才希望老大能稍微优化一下这里,提升jf的容错性,并且很容易实现。

至于你说mybatis也是这样的,但并不代表mybatis的做法就是对的啊
我承认没资格要求mybatis能按照咱们的要求改。
但幸好,我们还有一个能听得进建议的 @jfinal

JFinal

2018-09-19 17:22

@netwild 这其实是个权衡问题,要加这个功能也就一两行代码的事,极其容易

但是,jfinal 是极度追求性能的,如果对所有 sql 都去判断一下是不是有分号结尾,然后做个切分,这个多少会拉低一点性能

然后再考虑一下这种情况出现的概率,jfinal 诞生七年多,开源六年多,一共有两个人反馈过这个问题,为了响应两个人的需求,而去切分 sql,这个显然不划算

然后再从合理性方面考虑, jfinal 的数据库操作仅仅是对 JDBC 的一个极薄封装,在总体设计上是尽全力保持与 JDBC 的一致性,用户传入的 sql 与 para 都是原封不动扔给底层的 JDBC。如果判断分号并做切分这个显然不符合 jfinal 一贯的设计理念,JDBC 本身不支持这样的 sql, jfinal 并没有太多理由要去支持

用户的需求是多样化的,永无止尽的,jfinal 如果要去满足所有需求一定会变得学习成本极高、体积极大,最终会变得谁的需求都满足不了

所以关键就在于根据设计、成本、概率等等因素,做权衡取舍

JFinal

2018-09-19 17:39

最后再补充几句,这个完全不叫 “坑”,所谓 “坑” 是指很明显的错误做法或者设计,我记得是没有哪款 ORM 框架是自动去除过分号结尾字符的

如果按照你的逻辑,那么所有的 ORM 框架都有这个 “坑”

话说回来,就算所有 ORM 框架没有支持去除分号,也不能说明去除就不好。 不去除的原因还得看我上条回复,简单说就两个字:权衡

热门反馈

扫码入社