尧图精选

Mybatis高级进阶

🕒 发布时间:2026/10/2 12:52:35 📁 来源:尧图网络
一、引言在完成 MyBatis 基础 CRUD 与配置学习之后我们进入更核心的进阶阶段。本篇文章聚焦两大主题高级核心特性动态 SQL、复杂关联映射、缓存机制与生态整合与工程化落地Spring 原生整合、SpringBoot 3.x 自动整合、工程化工具提效。掌握这些能力你就能从容应对复杂业务场景并顺利融入企业级项目开发流程。二、高级核心特性本阶段目标掌握 MyBatis 核心高级能力应对复杂业务场景开发。2.1 动态 SQL 全语法实战#{}与${}的区别面试高频在动态 SQL 中#{}与${}是两种不同的参数占位方式理解它们的区别对安全与性能至关重要#{}预编译占位符MyBatis 会将其替换为?通过PreparedStatement预编译后传入参数能有效防止 SQL 注入是推荐使用的方式。${}字符串拼接MyBatis 会直接将参数值拼接到 SQL 语句中不做预编译存在 SQL 注入风险仅适用于表名、列名、排序字段等无法使用占位符的场景。!-- #{} 预编译安全 --selectidfindByNameresultTypeUserSELECT * FROM user WHERE name #{name}/select!-- ${} 字符串拼接仅用于表名/列名/排序等 --selectidselectByOrderresultTypeUserSELECT * FROM ${tableName} ORDER BY ${orderColumn}/select对比项#{}${}预编译是?占位否直接拼接SQL 注入风险无有适用场景值参数where 条件、insert 值等表名、列名、排序字段推荐程度优先使用谨慎使用动态 SQL 是 MyBatis 最强大的特性之一它让我们可以在 XML 中编写灵活的条件查询与更新语句避免拼接 SQL 的繁琐与安全隐患。核心标签if、choose/when/otherwiseif标签用于实现多条件动态拼接当条件成立时将标签内的 SQL 片段拼接到主语句中selectidfindByConditionresultTypeUserSELECT * FROM user WHERE 1 1iftestname ! null and name ! AND name #{name}/ififtestemail ! nullAND email #{email}/if/selectchoose/when/otherwise类似于 Java 中的switch用于「多选一」的场景只会命中第一个满足条件的分支selectidfindByPriorityresultTypeUserSELECT * FROM user WHERE status 1choosewhentestpriority highAND level 3/whenwhentestpriority mediumAND level 2/whenotherwiseAND level 1/otherwise/choose/select简化标签where、set手动书写WHERE 1 1并不优雅。where标签会自动处理 SQL 拼接后的多余AND、OR关键字selectidfindByConditionresultTypeUserSELECT * FROM userwhereiftestname ! null and name ! AND name #{name}/ififtestemail ! nullAND email #{email}/if/where/selectset标签用于动态更新语句自动处理多余逗号updateidupdateUserUPDATE usersetiftestname ! nullname #{name},/ififtestemail ! nullemail #{email},/if/setWHERE id #{id}/update批量操作foreachforeach标签支持批量插入、批量查询大幅提升数据操作效率。批量插入示例insertidbatchInsertINSERT INTO user (name, email) VALUESforeachcollectionlistitemitemseparator,(#{item.name}, #{item.email})/foreach/insert批量查询IN 条件示例selectidselectByIdsresultTypeUserSELECT * FROM user WHERE id INforeachcollectionidsitemidopen(close)separator,#{id}/foreach/select进阶技巧sql/includesql标签用于抽取公共 SQL 片段include用于引用实现代码复用sqliduserColumnsid, name, email, create_time/sqlselectidselectAllresultTypeUserSELECTincluderefiduserColumns/FROM user/select2.2 复杂关联映射一对一关联association通过association完成用户-用户档案的关联映射resultMapidUserWithProfileMaptypeUseridpropertyidcolumnid/resultpropertynamecolumnname/associationpropertyprofilejavaTypeUserProfileidpropertyidcolumnprofile_id/resultpropertyaddresscolumnaddress//association/resultMap一对多关联collection通过collection完成部门-员工列表的集合映射resultMapidDeptWithEmpsMaptypeDepartmentidpropertyidcolumnid/resultpropertynamecolumnname/collectionpropertyemployeesofTypeEmployeeidpropertyidcolumnemp_id/resultpropertynamecolumnemp_name//collection/resultMap嵌套查询 vs 嵌套结果关联映射有两种实现方式需要根据场景权衡嵌套查询先查主表再根据外键逐条发起子查询。实现简单但可能触发多次查询产生N1 查询问题。嵌套结果通过一条 JOIN SQL 一次查出所有数据由 MyBatis 完成结果映射。性能更优是生产环境的推荐选择。!-- 嵌套结果一条 JOIN 查出所有数据 --selectidselectDeptWithEmpsresultMapDeptWithEmpsMapSELECT d.id, d.name, e.id AS emp_id, e.name AS emp_name FROM department d LEFT JOIN employee e ON d.id e.dept_id WHERE d.id #{id}/select2.3 缓存机制原理与实战一级缓存一级缓存是SqlSession 级别的缓存默认开启。同一 SqlSession 内重复查询会命中缓存避免重复访问数据库。需要注意的失效场景执行增删改操作后缓存会被清空手动调用sqlSession.clearCache()会清空缓存不同 SqlSession 之间不共享一级缓存。try(SqlSessionsessionsqlSessionFactory.openSession()){Useruser1session.selectOne(selectUser,1);Useruser2session.selectOne(selectUser,1);// 命中一级缓存System.out.println(user1user2);// true}二级缓存二级缓存是Mapper 级别的缓存跨 SqlSession 共享。开启方式是在 Mapper XML 中添加配置cacheevictionLRUflushInterval60000size512readOnlytrue/使用二级缓存需要注意生产避坑点脏数据问题多表关联查询时若另一张表的数据被修改缓存不会自动失效可能读到脏数据序列化要求缓存对象需要实现Serializable接口readOnlyfalse时建议仅在查询频率高、数据变更少的场景开启。缓存失效场景分析场景一级缓存二级缓存同一 SqlSession 重复查询命中命中跨 SqlSession 查询不命中命中执行增删改清空清空默认手动 clearCache()清空不清空理解这些失效场景能有效避免业务中出现脏数据问题。三、生态整合与工程化落地本阶段目标对接 Spring/SpringBoot融入企业级项目开发流程。3.1 Spring 原生整合 MyBatis整合核心依赖原生整合需要引入mybatis-spring与spring-jdbc依赖dependencygroupIdorg.mybatis/groupIdartifactIdmybatis-spring/artifactIdversion3.0.3/version/dependencydependencygroupIdorg.springframework/groupIdartifactIdspring-jdbc/artifactIdversion6.1.0/version/dependency配置 SqlSessionFactoryBean配置SqlSessionFactoryBean注入数据源实现配置文件与 Spring 容器的融合beanidsqlSessionFactoryclassorg.mybatis.spring.SqlSessionFactoryBeanpropertynamedataSourcerefdataSource/propertynamemapperLocationsvalueclasspath:mapper/*.xml/propertynametypeAliasesPackagevaluecom.demo.entity//bean配置 MapperScannerConfigurer配置MapperScannerConfigurer自动批量扫描 Mapper 接口并注入 Spring 容器beanclassorg.mybatis.spring.mapper.MapperScannerConfigurerpropertynamebasePackagevaluecom.demo.mapper/propertynamesqlSessionFactoryBeanNamevaluesqlSessionFactory//bean理解 SqlSessionTemplateSqlSessionTemplate是 MyBatis-Spring 的核心它具备线程安全特性替代原生 SqlSession 实现自动管理无需手动关闭资源AutowiredprivateSqlSessionTemplatesqlSessionTemplate;publicUserfindUser(Longid){returnsqlSessionTemplate.selectOne(com.demo.mapper.UserMapper.selectById,id);}3.2 SpringBoot 3.x 自动整合引入起步依赖引入mybatis-spring-boot-starter起步依赖实现零 XML 快速配置dependencygroupIdorg.mybatis.spring.boot/groupIdartifactIdmybatis-spring-boot-starter/artifactIdversion3.0.3/version/dependencyapplication.yml 配置在application.yml中配置 MyBatis 参数Mapper 路径、别名包、驼峰映射等mybatis:mapper-locations:classpath:mapper/*.xmltype-aliases-package:com.demo.entityconfiguration:map-underscore-to-camel-case:true理解 MybatisAutoConfigurationMybatisAutoConfiguration是 SpringBoot 自动配置的核心类它会在应用启动时自动完成以下工作读取mybatis.*配置项自动创建SqlSessionFactoryBean自动扫描Mapper注解的接口并注册为 Bean自动注入SqlSessionTemplate。SpringBootApplicationMapperScan(com.demo.mapper)publicclassApplication{publicstaticvoidmain(String[]args){SpringApplication.run(Application.class,args);}}3.3 工程化工具提效MyBatisX 插件MyBatisX 是 IDEA 中的高效插件支持一键生成 Mapper 接口、XML、实体类在 Mapper 接口与 XML 之间快速跳转关联代码提供代码补全与语法校验。MyBatis Generator 逆向工程MyBatis Generator 根据数据库表自动生成基础 CRUD 代码减少重复劳动generatorConfigurationcontextidmysqltargetRuntimeMyBatis3SimplejdbcConnectiondriverClasscom.mysql.cj.jdbc.DriverconnectionURLjdbc:mysql://localhost:3306/demouserIdrootpassword123456/javaModelGeneratortargetPackagecom.demo.entitytargetProjectsrc/main/java/javaClientGeneratortargetPackagecom.demo.mappertargetProjectsrc/main/javatypeXMLMAPPER/tabletableNameuser//context/generatorConfiguration整合 PageHelper 分页插件PageHelper 是常用的物理分页插件一行代码即可实现分页PageHelper.startPage(1,10);ListUserusersuserMapper.selectAll();PageInfoUserpageInfonewPageInfo(users);dependencygroupIdcom.github.pagehelper/groupIdartifactIdpagehelper-spring-boot-starter/artifactIdversion1.4.7/version/dependency四、总结本文系统梳理了 MyBatis 的高级核心特性与生态整合方案动态 SQL掌握if、choose、where、set、foreach、sql/include等标签灵活应对复杂查询与批量操作复杂关联映射区分association与collection优先使用嵌套结果规避 N1 问题缓存机制理解一级缓存与二级缓存的作用域、失效场景与生产避坑点生态整合掌握 Spring 原生整合与 SpringBoot 3.x 自动整合两种方式工程化提效善用 MyBatisX、Generator 逆向工程与 PageHelper 分页插件。掌握这些能力你就能在企业级项目中高效、稳健地使用 MyBatis 完成复杂业务开发。
上一篇/下一篇内容由系统自动关联 返回资讯列表 →