mybatis-plus
mybatis-plus copied to clipboard
别名带有SQL转义字符 ` 导致分页优化了LEFT JOIN
当前使用版本(必填,否则不予处理)
mybatis-plus-extension-3.5.3.1.jar
该问题是如何引起的?(确定最新版也有问题再提!!!)
在自定义插件拦截器 拼写SQL时,交给分页插件时分页插件优化了LEFT(根据优化条件:条件中包含了 LEFT JOIN 表 的别名 不进行移除,而我的SQL条件中是存在的)
SELECT
su.`user_id`,
su.`dept_id`,
su.`username`,
su.`nick_name`,
su.`user_type`,
su.`email`,
su.`phonenumber`,
su.`sex`,
su.`avatar`,
su.`status`,
su.`del_flag`,
su.`login_ip`,
su.`login_date`,
su.`create_by`,
su.`create_time`,
su.`update_by`,
su.`update_time`,
su.`remark`,
sd.dept_name
FROM
sys_user su
LEFT JOIN sys_dept sd ON su.dept_id = sd.dept_id
WHERE
su.del_flag = '0'
AND (
`sd`.dept_id = 105
OR `su`.dept_id IN (
SELECT
dept_id
FROM
`sys_role_dept`
WHERE
FIND_IN_SET( role_id, '2,100' )))
ORDER BY
su.`create_time`
优化后:
SELECT
COUNT(*) AS total
FROM
sys_user su
WHERE
su.del_flag = '0'
AND (
`sd`.dept_id = 105
OR `su`.dept_id IN (
SELECT
dept_id
FROM
`sys_role_dept`
WHERE
FIND_IN_SET( role_id, '2,100' )))
DEUBG后发现此段代码:
if (rightItem instanceof Table) {
Table table = (Table) rightItem;
str = Optional.ofNullable(table.getAlias()).map(Alias::getName).orElse(table.getName()) + StringPool.DOT;
} else if (rightItem instanceof SubSelect) {
SubSelect subSelect = (SubSelect) rightItem;
/* 如果 left join 是子查询,并且子查询里包含 ?(代表有入参) 或者 where 条件里包含使用 join 的表的字段作条件,就不移除 join */
if (subSelect.toString().contains(StringPool.QUESTION_MARK)) {
canRemoveJoin = false;
break;
}
str = subSelect.getAlias().getName() + StringPool.DOT;
}
// 不区分大小写
str = str.toLowerCase();
if (whereS.contains(str)) {
/* 如果 where 条件里包含使用 join 的表的字段作条件,就不移除 join */
canRemoveJoin = false;
break;
}
str = subSelect.getAlias().getName() + StringPool.DOT;
只是alias
+ .
而少了 MYSQL 转义字符 `
重现步骤(如果有就写完整)
报错信息
去掉转义字符
是否具有转义字符的两个sql是等价的,mp应该对这两种情况都做好兼容和支持。个人觉得,不应该强制用户不加转义字符
为了你目前这种极端情况添加判断也没必要
是否具有转义字符的两个sql是等价的,mp应该对这两种情况都做好兼容和支持。个人觉得,不应该强制用户不加转义字符
我觉得也是,我是用转义字符 是为了避免别名与关键字冲突,也是为了兼容一下框架的CRUD,框架的CRUD似乎没有加入别名,出于此考虑才选择拼接SQL时使用转义字符包裹
干脆自己重新写一个. 或者fork自己改改.
是否具有转义字符的两个sql是等价的,mp应该对这两种情况都做好兼容和支持。个人觉得,不应该强制用户不加转义字符
为了你目前这种极端情况添加判断也没必要
这边也遇到了这段代码引发的问题,走的是第一个if分支。
select * from a left join `b` on a.x = b.x where b.y = xxx
if (rightItem instanceof Table) {
Table table = (Table) rightItem;
str = Optional.ofNullable(table.getAlias()).map(Alias::getName).orElse(table.getName()) + StringPool.DOT;
}
虽然修改sql就能规避这个问题,但是给框架使用带来了极大的影响,不清楚的人都需要跟着debug一遍源码才知道问题所在
建议在判断条件是否覆盖left join右侧的表时,把可能的`字符去除掉