Mybatis Log Free IDEA插件Bug修复

一、问题

项目中一直使用Mybatis,通过Mybatis Log Free[1]插件打印执行的SQL语句,再抓出来执行或者检查逻辑,一直还挺好用的。

最近遇到一个问题,就是SQL参数值中如果包含了括号,生成的SQL语句参数替换后字符串外面没有‘’,造成执行异常。简单来说这种参数没有当作字符串值来替换。

比如对于SQL语句UPDATE mp_user SET name=? WHERE id=? AND name=?,如果name值为stone(sh),预期得到的SQL为UPDATE mp_user SET name=null WHERE id=null AND name=’stone(sh)’,实际得到的是UPDATE mp_user SET name=null WHERE id=null AND name=stone(sh)。

1
UPDATE mp_user SET name=? WHERE id=? AND name=?

stone(sh)```
UPDATE mp_user SET name=null WHERE id=null AND name=’stone(sh)’

1

UPDATE mp_user SET name=null WHERE id=null AND name=stone(sh)

1
2
3
4
5
6
7
8
9
10
11
12
13

这个参数少时也没啥问题,手工替换一下。但是遇到参数比较多都需要手工替换就有点麻烦。

# 二、原因

这其实是插件的一个bug。看问题描述应该是未识别带括号的字符值类型。

通过IDEA插件中github链接直接找源码翻了一下。

**github**![image](/images/wechat/img_ad500a83250c.png)

原作者单测中有相关逻辑,src/test/java/com/starxg/mybatislog/MyBatisLogConsoleFilterTest.java,加入问题场景很容易复现。

src/test/java/com/starxg/mybatislog/MyBatisLogConsoleFilterTest.java

1
2
3

Bug原因也很简单,类src/main/java/com/starxg/mybatislog/MyBatisLogConsoleFilter.java中函数parseParams逻辑不支持参数值带括号。会把找到的第一个括号中的值作为参数类型来解析,因为括号中不是有效类型因此默认原样输出。

src/main/java/com/starxg/mybatislog/MyBatisLogConsoleFilter.java

1

parseParams

1

static Queue<Map.Entry<String, String>> parseParams(String line) {       line = StringUtils.removeEnd(line, “\n”);       final String[] strings = StringUtils.splitByWholeSeparator(line, “, “);       final Queue<Map.Entry<String, String>> queue = new ArrayDeque<>(strings.length);       for (String s : strings) {           String value = StringUtils.substringBeforeLast(s, “(“);           // 下面代码中原作者会把的第一个括号中的值作为参数类型。这里修复方法是把最后一个括号中的值作为参数类型           //String type = StringUtils.substringBetween(s, “(“, “)”);           int lastOpen = s.lastIndexOf(‘(‘);           int lastClose = s.lastIndexOf(‘)’);           String type = lastOpen != -1 && lastClose != -1 && lastOpen < lastClose ? s.substring(lastOpen + 1, lastClose) : null;           if (StringUtils.isEmpty(type)) {               queue.offer(new AbstractMap.SimpleEntry<>(value, null));           } else {               queue.offer(new AbstractMap.SimpleEntry<>(value, type));           }       }       return queue;   }

1

static Queue<Map.Entry<String, String>> parseParams(String line) {       line = StringUtils.removeEnd(line, “\n”);       final String[] strings = StringUtils.splitByWholeSeparator(line, “, “);       final Queue<Map.Entry<String, String>> queue = new ArrayDeque<>(strings.length);       for (String s : strings) {           String value = StringUtils.substringBeforeLast(s, “(“);           // 下面代码中原作者会把的第一个括号中的值作为参数类型。这里修复方法是把最后一个括号中的值作为参数类型           //String type = StringUtils.substringBetween(s, “(“, “)”);           int lastOpen = s.lastIndexOf(‘(‘);           int lastClose = s.lastIndexOf(‘)’);           String type = lastOpen != -1 && lastClose != -1 && lastOpen < lastClose ? s.substring(lastOpen + 1, lastClose) : null;           if (StringUtils.isEmpty(type)) {               queue.offer(new AbstractMap.SimpleEntry<>(value, null));           } else {               queue.offer(new AbstractMap.SimpleEntry<>(value, type));           }       }       return queue;   }


这里修复方法也很简单,把最后一个括号中的值作为参数类型来解析即可。

# 三、后记

从github README看,这个插件原作者已经把这个插件从开源转收费了,不确定开源版本是否会继续维护和接受代码修复PR。如果其他同学需要临时升级的可以联系我获取升级zip包来修复。

![image](/images/wechat/img_22dfe23bbb9f.png)

Mybatis Log Free: https://github.com/starxg/mybatis-log-plugin-free

*https://github.com/starxg/mybatis-log-plugin-free*