)
一、引言摘要本文面向 MyBatis 初学者通过「基础认知 → 核心配置 → 高级特性」三阶段学习路线带你从零搭建可运行 Demo掌握 Mapper 代理开发、参数传递、动态 SQL、缓存机制与性能优化并附完整可运行的 CRUD 代码助你快速上手 SSM/Spring Boot 整合。很多同学在学 MyBatis 时容易陷入两个极端要么只背 API 不写代码要么直接上手 SSM 项目结果一脸懵。本文按「基础认知 → 核心配置 → 高级特性」三阶段拆解每阶段都配有可直接运行的代码帮你用最短时间建立完整知识框架。全文基于 MyBatis 3.5.16 MySQL 8.0建议边看边敲。二、基础认知与快速入门2.1 框架定位与核心优势先对比原生 JDBC、Hibernate/JPA、MyBatis 三者的差异方案SQL 控制权开发效率复杂 SQL/调优原生 JDBC完全自主低代码冗余灵活但繁琐Hibernate/JPA框架生成高全自动映射不够灵活MyBatis完全自主中高半自动灵活且可控原生 JDBC 的问题在于参数设置、结果集处理、资源关闭等样板代码太多一个简单的查询要写几十行。而 Hibernate 与 JPA 虽然全自动映射省事但在复杂 SQL、多表联查、性能调优上往往力不从心。MyBatis 恰好取中间路线SQL 由你掌控映射交给框架。这就是「半自动化 ORM」的设计理念。MyBatis 完整执行流程配置加载SQL 解析参数处理SQL 执行结果映射这条链路是后续所有阶段的地基建议在入门时就画在纸上理解每一步做了什么。2.2 最小 Demo 搭建第一步创建 Maven 项目引入核心依赖dependencygroupIdorg.mybatis/groupIdartifactIdmybatis/artifactIdversion3.5.16/version/dependencydependencygroupIdcom.mysql/groupIdartifactIdmysql-connector-j/artifactIdversion8.0.33/version/dependency第二步编写 mybatis-config.xml 全局核心配置文件?xml version1.0 encodingUTF-8 ?!DOCTYPEconfigurationPUBLIC-//mybatis.org//DTD Config 3.0//ENhttps://mybatis.org/dtd/mybatis-3-config.dtdconfigurationenvironmentsdefaultdevelopmentenvironmentiddevelopmenttransactionManagertypeJDBC/dataSourcetypePOOLEDpropertynamedrivervaluecom.mysql.cj.jdbc.Driver/propertynameurlvaluejdbc:mysql://localhost:3306/ssm_demo/propertynameusernamevalueroot/propertynamepasswordvalue123456//dataSource/environment/environmentsmappersmapperresourcemapper/UserMapper.xml//mappers/configuration第三步编写第一个 Mapper XML 映射文件?xml version1.0 encodingUTF-8 ?!DOCTYPEmapperPUBLIC-//mybatis.org//DTD Mapper 3.0//ENhttps://mybatis.org/dtd/mybatis-3-mapper.dtdmappernamespacecom.demo.mapper.UserMapperselectidselectByIdresultTypecom.demo.entity.UserSELECT * FROM user WHERE id #{id}/select/mapper第四步通过 SqlSessionFactoryBuilder 构建工厂并执行Stringresourcemybatis-config.xml;InputStreaminputStreamResources.getResourceAsStream(resource);SqlSessionFactorysqlSessionFactorynewSqlSessionFactoryBuilder().build(inputStream);try(SqlSessionsessionsqlSessionFactory.openSession()){Userusersession.selectOne(com.demo.mapper.UserMapper.selectById,1);System.out.println(user);}到这里你已经跑通了 MyBatis 的最小闭环配置加载 → SQL 解析 → 参数处理 → SQL 执行 → 结果映射。2.3 Mapper 代理开发模式上面用session.selectOne(全限定名, 参数)的方式虽然能用但字符串容易写错且没有类型检查。更推荐Mapper 代理开发模式接口全限定名必须与 XML 的namespace一致方法名必须与 SQL 语句的id一致参数与返回值类型也要对应。publicinterfaceUserMapper{UserselectById(Integerid);}调用userMapper.selectById(1)时实际是JDK 动态代理对象把方法调用转发给SqlSession再定位到对应的 SQL 语句执行。这样既保留了 SQL 的灵活性又获得了接口编程的类型安全。① 实体类 Userpackagecom.demo.entity;publicclassUser{privateIntegerid;privateStringuserName;privateStringemail;publicUser(){}publicUser(StringuserName,Stringemail){this.userNameuserName;this.emailemail;}publicIntegergetId(){returnid;}publicvoidsetId(Integerid){this.idid;}publicStringgetUserName(){returnuserName;}publicvoidsetUserName(StringuserName){this.userNameuserName;}publicStringgetEmail(){returnemail;}publicvoidsetEmail(Stringemail){this.emailemail;}OverridepublicStringtoString(){returnUser{idid, userNameuserName, emailemail};}}② Mapper 接口 UserMapperpackagecom.demo.mapper;importcom.demo.entity.User;importjava.util.List;importjava.util.Map;publicinterfaceUserMapper{// 新增返回自增主键intinsert(Useruser);// 按 id 查询UserselectById(Integerid);// 多条件查询Map 传参ListUsersearchUsers(MapString,Objectparams);// 动态更新非空字段intupdateUser(Useruser);// 单条删除intdeleteById(Integerid);// 批量删除intdeleteBatch(ListIntegerids);}③ Mapper XMLUserMapper.xml?xml version1.0 encodingUTF-8 ?!DOCTYPEmapperPUBLIC-//mybatis.org//DTD Mapper 3.0//ENhttps://mybatis.org/dtd/mybatis-3-mapper.dtdmappernamespacecom.demo.mapper.UserMapper!-- 新增useGeneratedKeys 回填自增主键 --insertidinsertuseGeneratedKeystruekeyPropertyidINSERT INTO user(user_name, email) VALUES(#{userName}, #{email})/insert!-- 按 id 查询 --selectidselectByIdresultTypecom.demo.entity.UserSELECT * FROM user WHERE id #{id}/select!-- 多条件查询Map 传参 动态 SQL --selectidsearchUsersresultTypecom.demo.entity.UserSELECT * FROM userwhereiftestuserName ! null and userName ! AND user_name LIKE CONCAT(%, #{userName}, %)/ififtestemail ! null and email ! AND email #{email}/if/where/select!-- 动态更新非空字段 --updateidupdateUserUPDATE usersetiftestuserName ! nulluser_name #{userName},/ififtestemail ! nullemail #{email},/if/setWHERE id #{id}/update!-- 单条删除 --deleteiddeleteByIdDELETE FROM user WHERE id #{id}/delete!-- 批量删除foreach 遍历 id 列表 --deleteiddeleteBatchDELETE FROM user WHERE id INforeachcollectionlistitemidopen(separator,close)#{id}/foreach/delete/mapper④ 测试入口 Mainpackagecom.demo;importcom.demo.entity.User;importcom.demo.mapper.UserMapper;importorg.apache.ibatis.io.Resources;importorg.apache.ibatis.session.SqlSession;importorg.apache.ibatis.session.SqlSessionFactory;importorg.apache.ibatis.session.SqlSessionFactoryBuilder;importjava.io.InputStream;importjava.util.Arrays;importjava.util.HashMap;importjava.util.List;importjava.util.Map;publicclassMain{publicstaticvoidmain(String[]args)throwsException{Stringresourcemybatis-config.xml;InputStreaminputStreamResources.getResourceAsStream(resource);SqlSessionFactorysqlSessionFactorynewSqlSessionFactoryBuilder().build(inputStream);try(SqlSessionsessionsqlSessionFactory.openSession(true)){// true 自动提交UserMappermappersession.getMapper(UserMapper.class);// 1. 新增主键自动回填UsernewUsernewUser(张三,zhangsanexample.com);mapper.insert(newUser);System.out.println(新增成功回填主键 id newUser.getId());// 2. 按 id 查询Userusermapper.selectById(newUser.getId());System.out.println(按 id 查询user);// 3. 多条件查询Map 传参MapString,ObjectparamsnewHashMap();params.put(userName,张);ListUserusersmapper.searchUsers(params);System.out.println(模糊查询结果users);// 4. 动态更新只更新 emailUserupdatenewUser();update.setId(newUser.getId());update.setEmail(zhangsan_newexample.com);mapper.updateUser(update);System.out.println(更新后mapper.selectById(newUser.getId()));// 5. 单条删除mapper.deleteById(newUser.getId());System.out.println(单条删除完成);// 6. 批量删除Useru1newUser(李四,lisiexample.com);Useru2newUser(王五,wangwuexample.com);mapper.insert(u1);mapper.insert(u2);mapper.deleteBatch(Arrays.asList(u1.getId(),u2.getId()));System.out.println(批量删除完成);}}}⑤ 建表 SQLCREATETABLEuser(idINTNOTNULLAUTO_INCREMENT,user_nameVARCHAR(50)DEFAULTNULL,emailVARCHAR(100)DEFAULTNULL,PRIMARYKEY(id))ENGINEInnoDBDEFAULTCHARSETutf8mb4;提示openSession(true)表示自动提交事务若用openSession()手动提交记得在操作后调用session.commit()。3.3 结果集映射体系自动映射开启mapUnderscoreToCamelCasetrue后user_name自动映射到userName。自定义 ResultMap解决字段名与属性名不匹配的映射问题resultMapiduserResultMaptypecom.demo.entity.Useridpropertyidcolumnid/resultpropertyuserNamecolumnuser_name/resultpropertyemailcolumnemail//resultMap4. 总结阶段核心目标关键产出阶段一2 天跑通最小 Demo理解执行流程可运行的查询 Demo阶段二3 天吃透全局配置熟练 CRUD完整 CRUD ResultMapMyBatis 的学习关键在于「SQL 在手映射无忧」。把两阶段路线走完你就能独立搭建一个基于 MyBatis 的数据访问层为后续 SSM/Spring Boot 整合打下坚实基础。5. 总结阶段核心目标关键产出阶段一2 天跑通最小 Demo理解执行流程可运行的查询 Demo阶段二3 天吃透全局配置熟练 CRUD完整 CRUD ResultMapMyBatis 的学习关键在于「SQL 在手映射无忧」。把三阶段路线走完你就能独立搭建一个基于 MyBatis 的数据访问层为后续 SSM/Spring Boot 整合打下坚实基础。