我使用 Db.paginateByFullSql 去重失败

1589011219(1).png1589011254(1).png

1589011160(1).png

String select = "select distinct project.*,(select name from syscode where id = express.order_status) as orderStatus ";

String sqlExceptSelect = " from operator,project left join express on express.express_number = project.express_number where project.isdeleted = 0 and project.id = operator.operator_id and operator.operator_type = '"+OperatorType.PROJECT_ADD+"'  and operator.operator_user_id = "+userId+" and project.status = '"+OrderState.OPEN+"' ";

String totalRowSql = "select count(*) " + sqlExceptSelect + where;

where +=" order by project.id desc"; 

log.info("新建项目---查询的sql为:" + select + sqlExceptSelect + where);

return Db.paginateByFullSql(pageNumber, pageSize, totalRowSql, select + sqlExceptSelect + where, paras.toArray());


评论区

JFinal

2020-05-10 16:00

这个纯粹就是 sql 没写对,仔细写一下 sql 就好

仰望蓝天

2020-05-10 17:12

@JFinal sql 在navicate里是可以运行的,是paginateByFullSql方法传的参数有问题吗? 但我也是按文档上写的传参的啊?

JFinal

2020-05-10 17:27

@仰望蓝天 单步调试进入 paginateByFullSql 内部,看看里面是哪个地方不对

要注意 mysql 数据库高版本对于 distinct 的语法有变动,如果不是用的 mysql ,注意要设置方言:
activeRecordPlugin.setDialect(...);

配置一下输出 sql ,再用 sql 去 navicat 中看看对不对:
activeRecordPlugin.setShowSql(true);

最后,jfinal 只是将你的 sql + para 直接扔给 JDBC,自身并不会干预 sql 的执行,只要你的 sql 能在 JDBC 下正常工作,就一定没问题

仰望蓝天

2020-05-11 14:55

@JFinal 我用的数据库是 sqlserver 2012,输出的sql语句是
SELECT
*
FROM
(
SELECT
row_number () OVER ( ORDER BY tempcolumn ) temprownumber, *
FROM
(
SELECT TOP
20 tempcolumn = 0,
DISTINCT project.*,
( SELECT name FROM syscode WHERE id = express.order_status ) AS orderStatus
FROM
operator,
project
LEFT JOIN express ON express.express_number = project.express_number
WHERE
project.isdeleted = 0
AND project.id = operator.operator_id
AND operator.operator_type = '9'
AND operator.operator_user_id = 22
AND project.status = 1
ORDER BY
project.id DESC
) vip
) mvp
WHERE
temprownumber > 0
,我发现这条语句的distinct是被放到了top的后面,所以才会报错。
在 jfinal 里是对我传入的findsql 进行了拼接。调用的是 SqlServerDialect 的 forPaginate 方法。里面的写法是
public String forPaginate(int pageNumber, int pageSize, StringBuilder findSql) {
int end = pageNumber * pageSize;
if (end <= 0) {
end = pageSize;
}
int begin = (pageNumber - 1) * pageSize;
if (begin < 0) {
begin = 0;
}
StringBuilder ret = new StringBuilder();
ret.append("SELECT * FROM ( SELECT row_number() over (order by tempcolumn) temprownumber, * FROM ");
// 这里没有判断当 findSql 里面有distinct 的情况
ret.append(" ( SELECT TOP ").append(end).append(" tempcolumn=0,");
ret.append(findSql.toString().replaceFirst("(?i)select", ""));
ret.append(")vip)mvp where temprownumber>").append(begin);
return ret.toString();
}

JFinal

2020-05-11 15:53

@仰望蓝天 找到原因以后,通过继承 SqlServerDialect 覆盖掉父类的 forPaginate 方法,改成自己需要的就可以

还有一种办法是写一个工具类,例如叫 MyDb.java
然后用 jfinal Db 这个工具类中已有的一些 Db.queryLong、Db.find 等功能组合出一个满足自己需求的 paginate 方法

JFinal

2020-05-11 15:54

@仰望蓝天 分页出现问题一般原因与解决办法在这里:
https://jfinal.com/doc/5-6

仰望蓝天

2020-05-11 15:56

解决好了,重写一下此方法就行了。代码如下:
@Override
public String forPaginate(int pageNumber, int pageSize, StringBuilder findSql) {
int end = pageNumber * pageSize;
if (end <= 0) {
end = pageSize;
}
int begin = (pageNumber - 1) * pageSize;
if (begin < 0) {
begin = 0;
}
StringBuilder ret = new StringBuilder();
ret.append("SELECT * FROM ( SELECT row_number() over (order by tempcolumn) temprownumber, * FROM ");
if (findSql.toString().replace("distinct", "DISTINCT").indexOf("DISTINCT") == -1) {
ret.append(" ( SELECT TOP ").append(end).append(" tempcolumn=0,");
ret.append(findSql.toString().replaceFirst("(?i)select", ""));
} else {
ret.append(" ( SELECT DISTINCT TOP ").append(end).append(" tempcolumn=0,");
ret.append(findSql.toString().replace("distinct", "").replace("DISTINCT", "").replaceFirst("(?i)select", ""));
}
ret.append(")vip)mvp where temprownumber>").append(begin);
return ret.toString();
}

JFinal

2020-05-11 16:03

@仰望蓝天 换了 dialect 就可以了对吧?

仰望蓝天

2020-05-11 16:17

@JFinal 是的,把 dialect 换成了我的

热门反馈

扫码入社