mybatis使用笔记、生命周期、拦截器等、类型转换

发布时间:2026/9/11 19:33:25

mybatis使用笔记、生命周期、拦截器等、类型转换 文章目录打印sql日志mybatis-config.xml方式application.yml里面配置配置类配置方式生命周期生命周期-StatementHandler生命周期-ParameterHandler生命周期-Executor生命周期-ResultSetHandlermybatis拦截器其他扫描方式select日志可以打出来update和delete语句未打印出来?mybatis拦截器及sql拦截器拦截并打印指定方法的语句拦截器日志排查过程mybatis打印的时间一定准吗?BaseTypeHandler类型转换批量模式(批量插入)批量模式-原生批量模式-mybatis-plus批量模式-处理大文本时性能较低其他文档mybatis用了那么久实际一直不明白做个笔记吧。千万不要以为mybatis简单里面有很多东西它的设计思路及以及很多东西都很有借鉴性否则也不会成为最流行的持久层框架。如果能把mybatis裂解的很深那么很有好处。打印sql日志实测mybatis-config.xml方式好用(记得注掉yml里的相关配置)mybatis-config.xml方式这种方式实测稳稳当当可以打印sql日志在有mybatis-config.xml文件的时候推荐用这个。settingssettingnamelogImplvalueSTDOUT_LOGGING/setting/settings那么如果没有mybatis-config配置文件呢?用properties或者yml配置也是可以的。application.yml里面配置只配置这一句好像还不行需要配置logmapper所在位置的包为debug?实测用yml配置的方式没有成功改用mybatis-config.xml配置成功了。写法一(推荐)mybatis:configuration:log-impl:org.apache.ibatis.logging.slf4j.Slf4jImpl 写法二(实测打印不出参数建议用Slf4jImpl比较好)mybatis:configuration:log-impl:org.apache.ibatis.logging.stdout.StdOutImpllogging:level:root:infocom.ttt.demo:debug# 这个对应mapper类的包路径级别必须设置为debug注主要就2点。1、配置日志级别为debug。(注必须是debug才会打印sql)2、查看执行过程。(包含参数等)上面这种配置方法好像有问题。本地debug的时候加入如下两个参数实测可以-Dlogging.level.java.sql.StatementDEBUG-Dlogging.level.java.sql.PreparedStatementDEBUG如下参数也可以考虑加上-Dlogging.level.org.apache.ibatisDEBUG-Dlogging.level.java.sql.ConnectionDEBUG这几个参数也可以一起加log4j.logger.org.mybatisDEBUGlog4j.logger.org.apache.ibatisDEBUGlog4j.logger.java.sql.StatementDEBUGlog4j.logger.java.sql.ResultSetDEBUGlog4j.logger.java.sql.PreparedStatementDEBUGlog4j.logger.com.baiwang.custom.common.daoDEBUG注如果是log4j.properties加在这里面就行不用在application.yml里面加了。如果没有log4j.properties文件或者没有其他地方来配置才考虑在application.yml里面加。实测加在log4j.properties里面就够用。配置类配置方式生命周期生命周期-StatementHandler1、在MyBatis准备执行SQL之前首先会创建Statement对象这时会触发对StatementHandler的拦截。2、使用StatementHandler拦截器可以在SQL语句被发送到数据库执行前进行自定义操作比如修改原始SQL语句、设置特殊的Statement属性等。生命周期-ParameterHandler1、在Statement准备执行之前ParameterHandler将会被调用以设置SQL语句中的参数。2、通过拦截ParameterHandler可以在SQL参数绑定前后进行操作。适用于复杂的参数处理逻辑比如加密/解密数据或者对特殊的参数格式进行处理。生命周期-Executor1、执行器Executor是整个执行过程的中心它会调用上述的StatementHandler和ParameterHandler来准备命令并执行。2、拦截Executor可以在SQL执行前后添加逻辑比如缓存的逻辑在查询语句执行前后检查和添加缓存。生命周期-ResultSetHandler1、SQL语句执行后如果有结果集返回MyBatis将使用ResultSetHandler来处理这些结果集将JDBC返回的ResultSet转化为MyBatis中指定的结果对象。2、拦截ResultSetHandler支持在结果集映射过程中插入自定义逻辑比如结果集的加工处理、性能统计等。mybatis拦截器接口代码publicinterfaceInterceptor{Objectintercept(Invocationinvocation)throwsThrowable;defaultObjectplugin(Objecttarget){returnPlugin.wrap(target,this);}defaultvoidsetProperties(Propertiesproperties){}}实现类有一些如ExtDataInterceptor、PageInterceptor等。注从这里也可以看出不同拦截器因为需求不通接口设计也不同例如springmvc的拦截器的preHandler()就带有return false的功能。 mybatis因为没有这个需求所以没有带。也就是说拦截器是不同的。其他扫描方式不只一种哪种都是可以的。select日志可以打出来update和delete语句未打印出来?正常应该是都可以打印出来的应该不是设置控制的。那么问题来了如果sql执行出问题了会打印吗?感觉也会打印那么为什么没打印出来呢。。。所有方法都试了还是不行最后发现是mybatisConfig里面没有配置sql拦截器SqlPrintInterceptor。sqlPrintInterceptor()这个interceptor是mybatis的interceptor。所以应该多个思路是否重置了mybatis的拦截器。mybatis拦截器及sql拦截器拦截器代码Interceptor[]pluginsnewInterceptor[]{sqlPrintInterceptor(),otherInterceptor()};sessionFactoryBean.setPlugins(plugins);简单的说就是在sessionFactoryBean中设置plugins当然sessionFactoryBean可不只这点参数数据源等都是从这里设置。SqlPrintInterceptor代码在此不详述简单说就是实现Interceptor然后重写accept方法。拦截并打印指定方法的语句原理很简单intercept里面Invocation可以获取到MappedStatement再获取到statementId这个statementId就是mapper的方法名如com.test.UserMapper.saveUser;那么我们配置个拦截列表如果列表包含sql的statementId就打印sql否则不打印。OverridepublicObjectintercept(Invocationinvocation)throwsThrowable{MappedStatementmappedStatement(MappedStatement)invocation.getArgs()[0];ObjectparameterObjectnull;if(invocation.getArgs().length1){parameterObjectinvocation.getArgs()[1];}longstartSystem.currentTimeMillis();Objectresultinvocation.proceed();StringstatementIdmappedStatement.getId();logger.info(statementIdstatementId);// apache日志写法// 这个不拦截所有只有配置的方法才拦截if(interceptorMethodSet.contains(statementId)){BoundSqlboundSqlmappedStatement.getBoundSql(parameterObject);ConfigurationconfigurationmappedStatement.getConfiguration();StringsqlgetSql(boundSql,parameterObject,configuration);longendSystem.currentTimeMillis();longtimingend-start;if(logger.isInfoEnabled()||logger.isDebugEnabled()){// 这里打印sql}}else{// 不进行拦截}returnresult;}拦截器日志排查过程半天不打印sql搞了半天居然是Value注入set的问题改为注入string问题解决因为都可以用contains方法。这里不生效是哪里的问题呢?? // TODO1、按道理set肯定是可以注入的那么可能和值中间有.(点号)有关。2、和mybatis的statementId有关难道值中途改变了?感觉更加不像。3、和log的类型有关?apache日志还是log4j感觉这个更荒谬更不太可能。最后找到问题了居然是log打印的写法不对也是无语了。apache log的写法 不支持{}大括号的写法 log.info(sql);// apache log的写法 不支持{}大括号的写法slf4j的log写法 支持大括号的写法 log.info(sql{},sql);//mybatis打印的时间一定准吗?这个问题不能直接答准或不准。要有分析。mybatis执行语句的链路。1、从连接池获取连接。2、使用连接。3、归还连接。从日志来看是1、打印prepare语句。 # 1和2一般会一起打印出来。如果1、2没打印出来说明是僵死连接session就没创建成功。2、打印参数。3、打印执行结果。如果3和1、2时间间隔很长(1) 是慢sql拿出sql在数据库执行下如果也慢那就是慢sql。(2) 如果数据库执行不慢那就是其他问题例如连接池占满了或数据库响应慢。实际遇到过的场景1、自己加了sql拦截器加的不好全局sql都贼慢 # 去掉拦截器问题解决2、应用配置的连接池数太小排队等连接池耗费时间3、数据库负载到未响应的节点一直不响应BaseTypeHandler类型转换这个需要了解下它一直在默默运转虽然我们感知不到。机制不管你用它来做什么BaseTypeHandler的核心永远只有两个动作重写它的4个核心方法其实就是在做这两件事从Java到数据库写重写setNonNullParameter方法。比如把明文变密文、把List变JSON字符串然后通过ps.setString(...)等方法交给数据库。从数据库到Java读重写getNullableResult方法。比如把密文变回明文、把JSON字符串变回List然后return给你的Java对象。批量模式(批量插入)批量模式主要有两种1、mybatis原生 # 即 openSession的时候指定batch模式2、mybatis-plus的batch方法 # 内置了batch模式注这个容易有个误区认为批量模式就是for循环单条执行只不过写到一个方法里面了。实际并不是这么简单batch模式是先把数据缓存再一次性写入所以性能会大幅度提高。批量模式-原生try(SqlSessionsqlSessionsqlSessionFactory.openSession(ExecutorType.BATCH)){DimApiCallLogMapperbatchMappersqlSession.getMapper(DimApiCallLogMapper.class);for(DimApiCallLogl:sub){batchMapper.insert(l);}sqlSession.flushStatements();sqlSession.commit();}catch(Exceptione){log.error(批量新增维度API调用日志失败本批{}, serialNo{}, callStatus{},sub.size(),sub.get(0).getSerialNo(),sub.get(0).getCallStatus(),e);}批量模式-mybatis-plusbatch方法内置了批量机制所以性能本身就是比较高的。批量模式-处理大文本时性能较低实际遇到过3个longtext字段1000条批量一次要12s。longtext本来就慢单条也慢批量更慢时间会消耗在组装数据cpu和内存拆解等写库是甚至也要写多页。例如3个字段如果都超过了16k那么一次插入要4次io(1次主数据3次扩展页)性能慢很多。其他文档一文搞懂Mybatis执行原理 # 这篇文章不错mybatis相关文档https://mybatis.org/mybatis-3/https://mybatis.org/mybatis-3/logging.html # 日志锚点https://mybatis.plus/ # mybatis-plus文档
延伸阅读

更多相关文章

2026/9/11 19:33:25

DevOps与商业场景实战:从工具链到价值实现

1. 项目概述 "开发运维与商业场景实战"这个标题让我想起了多年前第一次参与企业级项目部署时的场景。当时作为新人,我完全无法理解为什么一个简单的功能上线需要经过那么多复杂流程。直到后来自己踩过各种坑,才真正明白DevOps和商业场景结合的…

2026/9/11 19:33:25

增强缓存错误报告:从模糊日志到精准排障的可观测性实践

1. 为什么缓存错误报告需要“增强”:一次排查事故的反思在数据库或分布式系统的日常运维里,缓存承担着给热数据加速的重任。但缓存不是保险箱,它也会出错:数据满了被逐出、条目意外失效、并发写入互相覆盖、序列化反序列化异常………

2026/9/11 19:33:25

AutoMapper在.NET中的高效对象映射实践指南

1. AutoMapper核心价值与应用场景AutoMapper作为.NET生态中广泛使用的对象映射工具,其核心价值在于消除应用程序中繁琐的对象转换代码。在实际项目中,我们经常遇到DTO(Data Transfer Object)与领域模型、视图模型之间的相互转换需…

2026/9/11 20:13:29

STM32双ADC同步采样实现Boost升压电路电压电流监测与效率计算

简介:一套基于STM32与C语言实现的DC-DC高效升压电路工程包,面向嵌入式电源开发者与电子工程学习者,适合电池供电、太阳能系统等需要把低压直流提升至较高电压的应用场景,重点解决输入输出电压同步采样与精确稳压控制问题。工程基于…

2026/9/11 20:13:29

MinMax-H3音视频模型原理与ComfyUI实战指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/9/11 20:13:29

Python自动化QQ邮箱处理:提升3倍效率的实战方案

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/9/11 20:13:29

gRPC双向流实战:从基础原理到生产级流管理

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/9/11 20:13:29

树莓派Pico低功耗软件控制实战:从Dormant模式到可复现续航

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/9/11 20:08:29

单片机存储结构详解:主存、地址空间与Flash/SRAM实战分析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/9/10 16:39:38

超人会飞不算本事:系统稳定依赖清晰规则与边界设计

开头先不绕弯子。“#斯坦李吐槽dc 所以超人是无缘无故会飞的嘛哈哈哈哈哈哈哈锤哥真是技术人才啊!#雷神 #复联”这类调侃式短标题,第一波冲击力在于它把两个宇宙的角色塞进同一个吐槽箱里,但细想一下就能发现,它真正碰到的根本不是…

2026/9/10 11:16:38

超人VS蜘蛛侠:拆解超级IP的影响力与传播方法论

把“蜘蛛侠 vs 超人”放在 CSDN 上聊,可能很多人第一反应是走错片场了。但如果把这两个角色看成“两个持续运营了 80 多年的文化产品”,你会发现,这场比较本质上是两个不同 IP 策略的长期结果对比:超人赢在定义了整个超级英雄题材…

2026/9/9 16:31:09

基于CNN的调制信号识别:MATLAB实现时频图分类实战

简介:本资源是一套面向通信工程与信号处理方向学习者、研究者的深度学习实践方案,聚焦调制信号自动检测与识别这一典型无线通信任务,解决传统方法依赖人工特征、低信噪比下性能下降等痛点。压缩包共12个文件(10.73MB)&…

2026/9/10 12:32:02

USB Type-C PCB布局分区设计:电源、高速信号与PD协议全攻略

做硬件这行,Type-C接口算是典型的“看着简单,做起来全坑”的东西。光引脚就24个,高低速信号、电源、控制线全部塞在一个小小的连接器里,如果PCB布局不做规划,打样回来基本就是“插上没反应”、“高速掉线”、“静电一打…

2026/9/10 15:19:50

系统编程学习原型如何补齐稳定性边界

系统编程学习原型如何补齐稳定性边界预算有限时&#xff0c;我先优化明显多余的复制&#xff0c;而不是猜测性地换容器。用借用传递只读数据通常就能减少分配&#xff1a; fn parse(line: &str) -> Result<Item, Error> { /* ... */ }用基准确认热点确实在分配&am…

2026/9/10 15:49:53

雨花区哪家财务公司代理记账比较好?

在雨花区&#xff0c;企业处理财税事务常常面临诸多挑战&#xff0c;选择一家靠谱的财务公司至关重要。湖南巨勤财务管理咨询有限公司就是本地正规实体财税服务机构&#xff0c;深耕本地工商财税行业多年&#xff0c;熟悉当地工商局、税务局最新政策与申报流程。主营公司注册、…

还想了解更多?直接咨询顾问

免费诊断 + 免费方案 + 透明报价。

全国咨询热线400-8866-253
免费获取方案
咨询二维码