Mybatis日志参数快速替换占位符工具的详细步骤

作者:cola.wz 时间:2023-09-30 21:29:36 

Mybatis log printf工具网页地址: http://www.feedme.ltd/log.html

Mybatis执行的sql的打印格式为:

2020-08-04 09:16:44 -DEBUG - [io-8888-exec-5] .mapper.operation.OperationMapper.insert.        debug 145 : ==>  Preparing: INSERT INTO tulu.t_log_operation (id, module, module_description, type, method, operator, operate_time) VALUES (?, ?, ?, ?, ?, ?, unix_timestamp(now()))
2020-08-04 09:16:44 -DEBUG - [io-8888-exec-5] .mapper.operation.OperationMapper.insert.        debug 145 : ==> Parameters: 2743672230717162752(Long), 1(Integer), 登录(String), 3(Integer), com.simba.tuloosa.controller.auth.LoginController.nativeLogin(String), 6d63b98cbe5e42d18c126da149162404(String)
2020-08-04 09:16:44 -DEBUG - [io-8888-exec-5] .mapper.operation.OperationMapper.insert.        debug 145 : <==    Updates: 1

IDEA里有一个插件Mybatis log plugin可以帮我们快速的提取参数拼成完整的SQL语句执行,以快速排错,但是很可惜,他是收费的ε=(&acute;ο`*)))唉,整来整取也没法破解,算了,不如自己写一个挂到公网上,也能复制sql随时拼接,纯js即可。

下面我们来逐步分析一下需要的步骤:

  1. 首先需要提取出preparedStatement语句

  2. 提取出所有的参数,String类型还需要手动添加引号

  3. 将statement中的占位符?替换为对应的参数

很简单吧,就这三步即可。接下来动手操作。

1、提取statement:只需截取从Preparing到行尾的\n即可


// str为完整的三行或两行SQL 提取预编译语句
let prepare = str.substring(str.indexOf('Preparing') + 11, str.indexOf('\n'))

indexOf(str: string):提取第一个匹配到的字符串的位置,返回其索引值

2、提取参数:只需截取从Parameters到其行尾的\n即可

这时我们需要提取到str的第二个\n换行符,怎么提取某个字符串中的第n个字符串呢?

indexOf()函数在js中是有重载的,默认提取第一个匹配的。它可以接受第二个参数,可以传入一个起始位置,即从position(索引)开始取第一个匹配的。


// js api
indexOf(searchString: string, position?: number): number;

分析:取第二个\n,我们可以将第一个\n的索引传入再加1;取第三个\n,则将第二个\n的索引传入加1,以此类推,所以这是一个递归函数,实现如下


// 返回字符串str中的第n字符串reg在str中的索引值index
function index(str, reg, n) {
if (!str || !reg || n <= 0) return -1
// 先求出第一个,再递归n-1
if (n === 1) {
return str.indexOf(reg)
}
// 注意n-1的索引后一定要加1,负责会一直是第一个reg的索引
return str.indexOf(reg, index(str, reg, n - 1) + 1)
}

接下来先测试一下index函数,打印正确


const str = 'hello world ok'
const reg = '0'
console.log(index(str, reg, 3)) // 求第三个o的索引,打印结果是12,正确

完成函数提取,所以回到上面的步骤,继续提取第二个\n的位置


// 获取参数字符串,去掉所有空格
const params = str.substring(str.indexOf('Parameters') + 12, index(str, '\n', 2)).replace(/ /g, '')

获取参数后以逗号切割,返回是一个字符串参数数组


const array = params.split(',')
// ['2743672230717162752(Long)','1(Integer)','登录(String)','3(Integer)']

提取完毕,则进行第三步的替换

3、替换参数


// 遍历数组,每次调用一次replace(old, new)即可,对字符串参数需要加上引号
array.map(item => {
// 获取每个参数值
let newValue = item.substring(0, item.indexOf('('))
// 获取参数类型
const type = item.substring(item.indexOf('(') + 1, item.indexOf(')'))
if ('String' === type) {
newValue = "'" + newValue + "'"
}
prepare = prepare .replace('?', newValue)

})
// 遍历完毕,所有的占位符也就被参数替换完成啦
console.log(prepare)
// INSERT INTO tulu.t_log_operation (id, module, module_description, type, method, operator, operate_time) VALUES (2743672230717162752, 1, '登录', 3, 'com.simba.tuloosa.controller.auth.LoginController.nativeLogin', '6d63b98cbe5e42d18c126da149162404', unix_timestamp(now()))

这样我们就实现了整个的js遍历、寻找、替换逻辑,整个过程就是不停的去indexOf(),substring()和replace(),是不是很简单呢,手写一个就不用了去找插件了。

我把这个网页放在了我的公网服务器上,访问地址是http://www.feedme.ltd/log.html
方便直接打开使用。

另外懒得写样式和DOM,所以在线引用了vue.js和elemenui,可能会出现有时候加载js文件速度比较慢的情况。

最后贴出整个HTML代码:


<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>Mybatis Log Helper</title>
<meta name=viewport content="width=device-width,initial-scale=1,maximum-scale=1,user-scalable=no" />
<link rel="shortcut icon" href="" />
<script src="https://unpkg.com/vue@2.6.11/dist/vue.js"></script>
<!-- 引入样式 -->
<link rel="stylesheet" href="https://unpkg.com/element-ui/lib/theme-chalk/index.css" rel="external nofollow" >
<!-- 引入组件库 -->
<script src="https://unpkg.com/element-ui/lib/index.js"></script>
<style>
#app {
margin-top: 70px;
display: flex;
justify-content: space-evenly;
align-items: center;
font-family: "Helvetica Neue", Helvetica, "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "微软雅黑", Arial, sans-serif;
}
</style>
</head>
<body>
<div id="app">
<el-input type="textarea" v-model="pre" placeholder="请复制输入Mybatis打印的日志,须完整Prepareing语句和Parameter语句"
 :rows="28" style="width: 600px"></el-input>
<el-button type="success" @click="convert" style="height: 60px; width: 80px;">转换</el-button>
<el-input type="textarea" v-model="res" placeholder="输出结果"
 :rows="28" style="width: 600px"></el-input>
</div>

<script type="text/javascript">
const app = new Vue({
el: '#app',
data() {
return {
 // 原始str
 pre: '',
 // 输出结果
 res: ''
}
},
methods: {
convert() {
 const str = this.pre
 if (str.indexOf('Preparing') == -1 || str.indexOf('Parameters') == -1) {
 this.$message({
 message: '请将Preparing和Parameters语句复制进来',
 type: 'error',
 center: true
 })
 }
 // str为完整的三行或两行SQL 提取预编译语句
 let prepare = str.substring(str.indexOf('Preparing') + 11, str.indexOf('\n'))
 // 获取参数,去空格
 const params = str.substring(str.indexOf('Parameters') + 12, index(str, '\n', 2)).replace(/ /g, '')
 // 参数数组
 const array = params.split(',')
 // 循环替换占位符,字符串方式替换每次替换第一个
 array.map(item => {
 // 获取每个参数值
 let newValue = item.substring(0, item.indexOf('('))
 // 获取参数类型
 const type = item.substring(item.indexOf('(') + 1, item.indexOf(')'))
 if ('String' === type) {
 newValue = "'" + newValue + "'"
 }
 prepare = prepare .replace('?', newValue)

})
 this.res = prepare
}
}
})

// 返回字符串str中的第n字符串reg在str中的索引值index
function index(str, reg, n) {
if (!str || !reg || n <= 0) return -1
// 先求出第一个,再递归n-1
if (n === 1) {
return str.indexOf(reg)
}
// 注意n-1的索引后一定要加1,负责会一直是第一个reg的索引
return str.indexOf(reg, index(str, reg, n - 1) + 1)
}
// 测试index函数
const str = 'hello world ok'
const reg = 'o'
console.log(index(str, reg, 3))
</script>
</body>
</html>

来源:https://blog.csdn.net/weixin_43030522/article/details/107778854

标签:Mybatis,日志参数,占位符
0
投稿

猜你喜欢

  • 完美解决idea moudle没有蓝色的小方块的问题

    2021-05-28 16:09:03
  • 实现一个Android锁屏App功能的难点总结

    2022-07-21 03:03:19
  • Java并发包之CopyOnWriteArrayList类的深入讲解

    2022-10-06 09:15:21
  • 深入浅析Mybatis的缺陷问题

    2023-07-19 19:39:46
  • 项目为什么引入log4j而不是logback代码

    2023-02-02 07:51:07
  • springboot整合微信支付sdk过程解析

    2021-12-30 22:47:29
  • Spring cloud alibaba之Gateway网关功能特征详解

    2022-10-26 18:22:28
  • Mybatis-Plus 全局配置无效的解决方案

    2022-06-29 12:46:02
  • C#访问SqlServer设置链接超时的方法

    2022-11-19 17:43:21
  • c#中值类型和引用类型的基础教程

    2021-10-20 18:03:41
  • android调试工具DDMS的使用详解

    2023-06-21 09:06:22
  • Java编程实现统计一个字符串中各个字符出现次数的方法

    2023-01-24 18:02:20
  • Android开发Jetpack组件WorkManager用例详解

    2023-05-09 03:27:07
  • Kotlin Flow操作符及基本使用详解

    2022-08-24 16:32:30
  • Android RecyclerView 实现快速滚动的示例代码

    2023-02-17 05:32:50
  • Java获取任意http网页源代码的方法

    2022-07-06 01:45:37
  • Swagger实现动态条件注入与全局拦截功能详细流程

    2023-11-23 13:41:05
  • java+SpringBoot设计实现评教系统

    2023-02-05 13:12:18
  • 如何使用C#将Tensorflow训练的.pb文件用在生产环境详解

    2023-02-12 21:25:59
  • SpringBoot整合腾讯云COS对象存储实现文件上传的示例代码

    2021-06-01 03:25:14
  • asp之家 软件编程 m.aspxhome.com