MyBatis持久层框架实战:从配置到优化全解析
1. MyBatis基础认知与环境准备MyBatis作为Java生态中最受欢迎的持久层框架之一其核心设计理念是通过XML或注解将SQL与程序代码解耦。我在2016年第一次接触MyBatis时就被它这种SQL可见性的设计哲学所吸引——开发者可以完全掌控SQL语句同时又不必处理JDBC那些繁琐的API调用。1.1 必备环境清单在开始配置前请确保已准备好以下环境以当前主流版本为例JDK 1.8推荐Amazon Corretto 11Maven 3.6.3注意配置阿里云镜像加速IDEIntelliJ IDEA或Eclipse with STS插件数据库MySQL 8.0或PostgreSQL 14经验提示新手常犯的错误是直接使用最新版本的MyBatis如3.5.10但实际企业项目中更多使用经过验证的稳定版如3.5.6。版本差异可能导致某些API行为不一致。1.2 Maven依赖配置在pom.xml中添加核心依赖时要注意依赖的作用域scopedependencies !-- 核心库 -- dependency groupIdorg.mybatis/groupId artifactIdmybatis/artifactId version3.5.6/version /dependency !-- 数据库驱动以MySQL为例 -- dependency groupIdmysql/groupId artifactIdmysql-connector-java/artifactId version8.0.28/version scoperuntime/scope /dependency !-- 日志实现推荐SLF4JLogback -- dependency groupIdch.qos.logback/groupId artifactIdlogback-classic/artifactId version1.2.11/version /dependency /dependencies2. 核心配置文件详解mybatis-config.xml是MyBatis的中枢神经系统我见过太多项目因为错误配置导致性能问题。下面这个模板经过我多个生产项目验证2.1 基础配置结构?xml version1.0 encodingUTF-8? !DOCTYPE configuration PUBLIC -//mybatis.org//DTD Config 3.0//EN http://mybatis.org/dtd/mybatis-3-config.dtd configuration settings setting namemapUnderscoreToCamelCase valuetrue/ setting namejdbcTypeForNull valueNULL/ setting namelogImpl valueSLF4J/ /settings typeAliases package namecom.example.model/ /typeAliases environments defaultdevelopment environment iddevelopment transactionManager typeJDBC/ dataSource typePOOLED property namedriver valuecom.mysql.cj.jdbc.Driver/ property nameurl valuejdbc:mysql://localhost:3306/test?useSSLfalseamp;serverTimezoneUTC/ property nameusername valueroot/ property namepassword value123456/ /dataSource /environment /environments mappers mapper resourcemapper/UserMapper.xml/ /mappers /configuration2.2 关键配置项解析配置项推荐值作用说明典型错误cacheEnabledtrue二级缓存开关在读写混合场景误开启lazyLoadingEnabledfalse延迟加载N1查询问题aggressiveLazyLoadingfalse侵略性延迟加载引发意外查询jdbcTypeForNullNULL空值处理导致NOT NULL约束冲突mapUnderscoreToCamelCasetrue字段自动转换与数据库设计冲突踩坑记录曾经有个项目因为aggressiveLazyLoadingtrue导致首页加载时意外触发200SQL查询最终通过Arthas定位到是MyBatis配置问题。3. XML映射文件实战3.1 基础CRUD示例以用户管理为例UserMapper.xml应该这样设计mapper namespacecom.example.mapper.UserMapper resultMap iduserResultMap typeUser id propertyid columnid/ result propertyuserName columnuser_name/ result propertycreatedAt columncreated_at jdbcTypeTIMESTAMP/ /resultMap select idselectById resultMapuserResultMap SELECT * FROM users WHERE id #{id} /select insert idinsert useGeneratedKeystrue keyPropertyid INSERT INTO users(user_name, email) VALUES(#{userName}, #{email}) /insert update idupdate UPDATE users SET user_name #{userName}, email #{email} WHERE id #{id} /update delete iddelete DELETE FROM users WHERE id #{id} /delete /mapper3.2 动态SQL技巧MyBatis最强大的特性之一是其动态SQL能力select idsearchUsers resultMapuserResultMap SELECT * FROM users where if testuserName ! null and userName ! AND user_name LIKE CONCAT(%, #{userName}, %) /if if testemail ! null AND email #{email} /if choose when teststatus active AND is_active 1 /when when teststatus inactive AND is_active 0 /when otherwise AND is_active IN (0, 1) /otherwise /choose /where ORDER BY trim prefixOverrides, if testorderBy name, user_name/if if testorderBy date, created_at/if /trim /select性能提示在MySQL中CONCAT函数会导致索引失效大数据量查询时应改用AND user_name LIKE #{userName}%形式并在调用处处理通配符。4. 高级配置与优化4.1 插件开发实战实现一个SQL执行时间统计插件Intercepts({ Signature(type StatementHandler.class, methodquery, args{Statement.class, ResultHandler.class}), Signature(type StatementHandler.class, methodupdate, args{Statement.class}) }) public class SqlCostInterceptor implements Interceptor { private static final Logger logger LoggerFactory.getLogger(SqlCostInterceptor.class); Override public Object intercept(Invocation invocation) throws Throwable { long start System.currentTimeMillis(); try { return invocation.proceed(); } finally { long cost System.currentTimeMillis() - start; StatementHandler handler (StatementHandler) invocation.getTarget(); String sql handler.getBoundSql().getSql(); logger.warn(SQL执行耗时: {}ms - {}, cost, sql.replaceAll(\\s, )); } } Override public Object plugin(Object target) { return Plugin.wrap(target, this); } Override public void setProperties(Properties properties) {} }在配置文件中注册插件plugins plugin interceptorcom.example.plugin.SqlCostInterceptor/ /plugins4.2 批量操作优化使用BatchExecutor提升批量插入性能try (SqlSession session sqlSessionFactory.openSession(ExecutorType.BATCH)) { UserMapper mapper session.getMapper(UserMapper.class); for (int i 0; i 10000; i) { mapper.insert(new User(user_ i, testexample.com)); if (i % 1000 0) { session.flushStatements(); // 分批提交 } } session.commit(); }性能对比数据基于MySQL 8.0本地测试操作方式1万条数据耗时内存占用普通插入12.4s380MB批量模式1.8s45MB批处理rewriteBatchedStatements0.9s32MB关键配置在JDBC URL中添加rewriteBatchedStatementstrue参数可使批量性能再提升50%5. 生产环境避坑指南5.1 缓存踩坑实录一级缓存问题在同一个SqlSession中重复执行相同查询会直接返回缓存结果。这会导致在开启事务后即使数据库数据已变更查询仍然返回旧值。解决方案// 方法一强制清空缓存 sqlSession.clearCache(); // 方法二在select标签上配置flushCache select idselectById resultMapuserResultMap flushCachetrue SELECT * FROM users WHERE id #{id} /select // 方法三使用不同的SqlSession5.2 类型处理器陷阱处理枚举类型时的正确方式public enum UserStatus { ACTIVE(1), INACTIVE(0); private final int code; // 构造方法、getter省略... } // 自定义类型处理器 public class UserStatusTypeHandler extends BaseTypeHandlerUserStatus { Override public void setNonNullParameter(PreparedStatement ps, int i, UserStatus parameter, JdbcType jdbcType) throws SQLException { ps.setInt(i, parameter.getCode()); } // 其他方法实现省略... }注册处理器typeHandlers typeHandler handlercom.example.handler.UserStatusTypeHandler javaTypecom.example.enums.UserStatus/ /typeHandlers5.3 SQL注入防御虽然MyBatis使用预编译语句但不当使用仍可能导致注入危险写法select idfindByOrder resultMapuserResultMap SELECT * FROM users ORDER BY ${orderBy} /select安全写法select idfindByOrder resultMapuserResultMap SELECT * FROM users ORDER BY choose when testorderBy nameuser_name/when when testorderBy datecreated_at/when otherwiseid/otherwise /choose /select6. 与Spring集成实践6.1 标准集成配置Configuration public class MyBatisConfig { Bean public SqlSessionFactory sqlSessionFactory( DataSource dataSource) throws Exception { SqlSessionFactoryBean factory new SqlSessionFactoryBean(); factory.setDataSource(dataSource); factory.setTypeAliasesPackage(com.example.model); // 配置XML映射文件位置 Resource[] mapperLocations new PathMatchingResourcePatternResolver() .getResources(classpath:mapper/*.xml); factory.setMapperLocations(mapperLocations); // 添加插件 factory.setPlugins(new SqlCostInterceptor()); return factory.getObject(); } Bean public MapperScannerConfigurer mapperScannerConfigurer() { MapperScannerConfigurer configurer new MapperScannerConfigurer(); configurer.setBasePackage(com.example.mapper); return configurer; } }6.2 事务管理配置Configuration EnableTransactionManagement public class TransactionConfig { Bean public PlatformTransactionManager transactionManager( DataSource dataSource) { return new DataSourceTransactionManager(dataSource); } }集成提示Spring Boot项目中更推荐使用mybatis-spring-boot-starter它会自动处理大多数基础配置版本兼容性问题也更少。

相关新闻

PHP实现CQRS读模型投影技术详解

PHP实现CQRS读模型投影技术详解

1. PHP读模型投影技术解析读模型投影(Read Model Projection)是CQRS架构中的核心概念,它通过将写模型的事件流转换为适合查询的读模型,解决了传统CRUD模式在高并发查询场景下的性能瓶颈。PHP作为动态类型语言,实现读模…

2026/10/16 7:37:47 阅读更多 →
GB2312、UTF-8、UCS-2编码对照:原理、转换与乱码排查实战

GB2312、UTF-8、UCS-2编码对照:原理、转换与乱码排查实战

1. 项目概述:为什么我们需要一张编码对应表?做开发或者数据处理的朋友,尤其是和中文、多语言环境打交道比较多的,肯定都遇到过编码问题。一个文件在A系统里打开是正常的,传到B系统就变成了一堆乱码;从数据库…

2026/10/13 9:24:38 阅读更多 →
XRAY漏洞扫描器实战:从安装配置到高级联动,打造自动化安全测试工作流

XRAY漏洞扫描器实战:从安装配置到高级联动,打造自动化安全测试工作流

1. 项目概述:为什么我们需要一个高效的漏洞扫描器?在安全测试的日常工作中,无论是渗透测试、红队演练还是日常的安全巡检,漏洞扫描都是最基础也是最耗时的环节之一。很多朋友可能用过 AWVS、Nessus 这类商业工具,功能强…

2026/10/15 4:48:44 阅读更多 →

最新新闻

Android校园论坛App开发实战:从架构设计到毕设答辩全攻略

Android校园论坛App开发实战:从架构设计到毕设答辩全攻略

1. 项目概述:为什么说这是最适合做毕设的Android选题之一校园信息论坛这个题目,几乎是每年计算机毕业设计里“常青树”级别的存在。我见过太多人选电商系统、选点餐App、选运动打卡,最后做到中期答辩才发现业务逻辑复杂到失控——订单状态机、…

2026/10/16 7:38:11 阅读更多 →
Ubuntu 20.04深度学习环境搭建:NVIDIA驱动+CUDA+cuDNN+PyTorch全攻略

Ubuntu 20.04深度学习环境搭建:NVIDIA驱动+CUDA+cuDNN+PyTorch全攻略

1. 深度学习环境搭建的整体思路与方案选型1.1 为什么选择这套组合搞深度学习环境搭建这件事,说简单也简单,说折腾也真折腾。我前后在不下十台机器上装过这套环境,从实验室的塔式工作站到租用的云主机,每次都会遇到不一样的问题。U…

2026/10/16 7:38:11 阅读更多 →
YOLOv10【第九章:模型导出、部署与加速篇·第9节】NCNN 部署 YOLOv10:算子兼容与后处理适配!

YOLOv10【第九章:模型导出、部署与加速篇·第9节】NCNN 部署 YOLOv10:算子兼容与后处理适配!

🏆 本文收录于 《YOLOv10实战:从入门到深度优化》 专栏。 该专栏系统复现并深度梳理全网主流 YOLOv10 改进方法与工程实战案例,覆盖分类、目标检测、实例分割、多目标追踪、关键点检测、旋转目标检测等多个方向,坚持 持续更新 + 深度解析 + 工程验证。 专栏将围绕 YOLOv10…

2026/10/16 7:38:11 阅读更多 →
STM32 HAL库内部Flash操作与固件大小读取方法详解

STM32 HAL库内部Flash操作与固件大小读取方法详解

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

2026/10/16 7:38:11 阅读更多 →
基于MP2642GR-Z与PIC18F8520的两串电池主动均衡系统设计

基于MP2642GR-Z与PIC18F8520的两串电池主动均衡系统设计

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

2026/10/16 7:38:11 阅读更多 →
手工扒带Grunge:用Ableton与Python构建音乐数据集

手工扒带Grunge:用Ableton与Python构建音乐数据集

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

2026/10/16 7:37:11 阅读更多 →

日新闻

个人 AI Agent 平台接入 TaoToken:统一 Key 与 API 通道的配置大纲

个人 AI Agent 平台接入 TaoToken:统一 Key 与 API 通道的配置大纲

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

2026/10/16 0:00:05 阅读更多 →
信号与系统频域分析作业解题指南

信号与系统频域分析作业解题指南

1. 作业背景与核心要求解析信号与系统作为电子信息类专业的核心基础课,其作业设计往往直接关联课程的核心知识框架。2026年春季第六次作业的布置,通常对应着课程进展到频域分析的关键阶段。根据常规教学进度推测,本次作业可能涉及以下核心内容…

2026/10/16 0:00:05 阅读更多 →
Django MVT实战:从零构建图书借阅系统,彻底搞懂Model-View-Template分层

Django MVT实战:从零构建图书借阅系统,彻底搞懂Model-View-Template分层

1. 从一个"四不像"的练手项目说起如果你已经看完了Django的官方教程前几章,跟着敲完了投票应用,大概会有一种"我好像会了,又好像什么都不会"的割裂感。教程里每个知识点都是拆开的——这一章讲模型,下一章讲视…

2026/10/16 0:00:05 阅读更多 →

周新闻

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

简介:基于 ARIMA、LSTM、Transformer 等模型的流感时间序列预测 Python 源码,面向计算机相关专业课程设计与期末大作业学生,以及项目实战学习者。内容覆盖预处理、平稳性检验、定阶、残差分析、多模型对比预测的完整时序建模流程,…

2026/10/15 16:18:54 阅读更多 →
影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别 做影刀RPA自动化,十个新手有八个栽在"往输入框里填东西"这件事上:要么填不进去,要么填了一半,要么直接把原来内容追加在后面。这背后的根因&…

2026/10/15 19:41:51 阅读更多 →
影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容 1. 认识影刀:什么场景该用RPA采小说数据 起点中文网的页面结构相对稳定——分类榜单、书籍详情、章节内容三块独立页面,跳转链路清晰。这种场景非常适合影刀自动化&#x…

2026/10/15 13:48:15 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

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

2026/10/15 0:14:36 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

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

2026/10/16 3:49:43 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

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

2026/10/15 9:49:14 阅读更多 →