杭州网站建设响应式,家乡网站设计目的,网站开发网页加载很慢怎么办,网站开发合作运营平台合同shigen坚持更新文章的博客写手#xff0c;擅长Java、python、vue、shell等编程语言和各种应用程序、脚本的开发。记录成长#xff0c;分享认知#xff0c;留住感动。 个人IP#xff1a;shigen 在使用mybatis-plus#xff08;mybatis#xff09;的时候#xff0c;往往需要… shigen坚持更新文章的博客写手擅长Java、python、vue、shell等编程语言和各种应用程序、脚本的开发。记录成长分享认知留住感动。 个人IPshigen 在使用mybatis-plusmybatis的时候往往需要打印完整的sql语句然而输出的日志不是很理想 因为sql语句中的关键字段信息都是用来代替的。那有什么方法实现完整的sql打印呢有是有的我记得IDEA的插件市场有一款插件可以实现完整sql的打印但是好像是要收费的。今天刷某音的时候看到了某博主分享了一下自己写了一个拦截器实现了sql完整的打印以下是实现的效果
可以看到了sql的执行时间和完整的sql语句。sql的执行时间没啥好说的关键是sql语句的完整打印。现在先来分享一下代码吧。
代码
controller的设计
这里仅展示关键的代码一个更新的操作一个分页查询的操作。 PostMapping(value update)public ResultString update(RequestBody Validated(value UpdateGroup.class) User user) {int update userMapper.updateById(user);return update 0 ? Result.ok(null) : Result.err(null);}GetMapping(value get)public ResultListUser get(RequestParam(value id, required false) Integer id,RequestParam(value name, required false) String name) {LambdaQueryWrapperUser queryChainWrapper new LambdaQueryWrapper();queryChainWrapper.eq(id ! null, User::getId, id);queryChainWrapper.eq(name ! null, User::getUsername, name);ListUser records userMapper.selectPage(new PageUser(0, 10), queryChainWrapper).getRecords();return Result.ok(records);}拦截器设计
虽然这里是mybatis-plus框架但是还是需要使用到mybatis的功能。
/*** author shigenfu* date 2024/6/16 10:01*/
Intercepts({Signature(type Executor.class, method query, args {MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class}),Signature(type Executor.class, method query, args {MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class, CacheKey.class, BoundSql.class}),Signature(type Executor.class, method update, args {MappedStatement.class, Object.class})
})
Slf4j
public class SqlInterceptor implements Interceptor {Overridepublic Object intercept(Invocation invocation) throws Throwable {// 统计sql执行耗时long startTime System.currentTimeMillis();Object proceed invocation.proceed();long endTime System.currentTimeMillis();String printSql null;try {printSql generateSql(invocation);} catch (Exception exception) {log.error(获取sql异常, exception);} finally {long costTime endTime - startTime;log.info(\n 执行SQL耗时{}ms \n 执行SQL{}, costTime, printSql);}return proceed;}private static String generateSql(Invocation invocation) {MappedStatement statement (MappedStatement) invocation.getArgs()[0];Object parameter null;if (invocation.getArgs().length 1) {parameter invocation.getArgs()[1];}Configuration configuration statement.getConfiguration();BoundSql boundSql statement.getBoundSql(parameter);// 获取参数对象Object parameterObject boundSql.getParameterObject();// 获取参数映射ListParameterMapping params boundSql.getParameterMappings();// 获取到执行的SQLString sql boundSql.getSql();// SQL中多个空格使用一个空格代替sql sql.replaceAll([\\s], );if (!ObjectUtils.isEmpty(params) !ObjectUtils.isEmpty(parameterObject)) {// TypeHandlerRegistry 是 MyBatis 用来管理 TypeHandler 的注册器 TypeHandler 用于在 Java 类型和 JDBC 类型之间进行转换TypeHandlerRegistry typeHandlerRegistry configuration.getTypeHandlerRegistry();// 如果参数对象的类型有对应的 TypeHandler则使用 TypeHandler 进行处理if (typeHandlerRegistry.hasTypeHandler(parameterObject.getClass())) {sql sql.replaceFirst(\\?, Matcher.quoteReplacement(getParameterValue(parameterObject)));} else {// 否则逐个处理参数映射for (ParameterMapping param : params) {// 获取参数的属性名String propertyName param.getProperty();MetaObject metaObject configuration.newMetaObject(parameterObject);// 检查对象中是否存在该属性的 getter 方法如果存在就取出来进行替换if (metaObject.hasGetter(propertyName)) {Object obj metaObject.getValue(propertyName);sql sql.replaceFirst(\\?, Matcher.quoteReplacement(getParameterValue(obj)));// 检查 BoundSql 对象中是否存在附加参数} else if (boundSql.hasAdditionalParameter(propertyName)) {Object obj boundSql.getAdditionalParameter(propertyName);sql sql.replaceFirst(\\?, Matcher.quoteReplacement(getParameterValue(obj)));} else {// SQL匹配不上带上“缺失”方便找问题sql sql.replaceFirst(\\?, 缺失);}}}}return sql;}private static String getParameterValue(Object object) {String value ;if (object instanceof String) {value object ;} else if (object instanceof Date) {DateFormat format DateFormat.getDateTimeInstance(DateFormat.DEFAULT, DateFormat.DEFAULT, Locale.CHINA);value format.format((Date) object) ;} else if (!ObjectUtils.isEmpty(object)) {value object.toString();}return value;}Overridepublic Object plugin(Object target) {return Plugin.wrap(target, this);}}直接贴的代码其实就是在sql执行完毕之后根据sql的template和sql参数进行的替换。 这里不分析代码希望能亲自debug看一下。 配置类
这里的配置我都写在了mybatis-plus的配置代码里边。
Configuration
MapperScan(value main.java.shigen.demo.dao)
public class MybatisPlusConfig {Beanpublic MybatisPlusInterceptor mybatisPlusInterceptor() {MybatisPlusInterceptor interceptor new MybatisPlusInterceptor();// 分页插件interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));// 乐观锁插件interceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());return interceptor;}Beanpublic ConfigurationCustomizer configurationCustomizer() {return configuration - {configuration.addInterceptor(new SqlInterceptor());};}
}以上就是核心的代码了实测遇到的问题有一个
分页查询的时候无法显示limit 0,10这个sql后缀
希望有时间的时候能够再次优化一下。同时也没有经过实际的项目测试只是简单的demo测试。仅具有参考价值无法保证实际的应用。
后记
在GPT上我也是尝试提问了一下发现在GPT3.5模型上没有给出满意的答复反而是GPT4.0给出了接近我上述代码的答案。最近也在学习AI相关的课程其中最重要的就是如何提问也就是pormpt。 插一点一点关于AI的思考AI其实完全可以替代人类但是不能替代人类的想象力。所以甭管在复杂的设计、再空前绝后的设计拥有想象力提问的能力都可以被AI很好的解答。
与shigen一起每天不一样