
Spring Boot 整合原生 MyBatis 实战基于 mybatis-spring-boot-starter 的 ORM 示例解析【免费下载链接】spring-boot-demo一个用来深入学习并实战 Spring Boot 的项目。项目地址: https://gitcode.com/gh_mirrors/sp/spring-boot-demo本篇技术指南以 spring-boot-demo 仓库中的 demo-orm-mybatis 模块为核心完整讲解 Spring Boot 如何通过 MyBatis 官方脚手架mybatis-spring-boot-starter与原生 MyBatis 进行整合。你将掌握从依赖引入、数据源与 MyBatis 配置、实体与 Mapper 编写到注解 SQL 与 XML 映射混用、单元测试验证的完整落地流程并理解MapperScan、map-underscore-to-camel-case、mapper-locations等关键配置的底层作用。模块概览官方 Starter 的零配置整合思路在 Spring Boot 出现之前整合 MyBatis 往往需要手动编写SqlSessionFactory、DataSource、SqlSessionTemplate等大量样板 Bean。而 MyBatis 官方提供的mybatis-spring-boot-starter充分利用 Spring Boot 的自动装配机制将这一过程大幅简化只需要引入一个依赖配置好数据源Mapper 接口即可直接注入使用。本模块demo-orm-mybatis的核心目录结构如下demo-orm-mybatis/ ├── pom.xml └── src ├── main │ ├── java/com/xkcoding/orm/mybatis │ │ ├── SpringBootDemoOrmMybatisApplication.java # 启动类声明 MapperScan │ │ ├── entity/User.java # 用户实体 │ │ └── mapper/UserMapper.java # Mapper 接口注解 XML 混用 │ └── resources │ ├── application.yml # 数据源 MyBatis 配置 │ ├── db/schema.sql # 建表脚本 │ ├── db/data.sql # 初始化数据 │ └── mappers/UserMapper.xml # XML 映射文件 └── test/java/com/xkcoding/orm/mybatis ├── SpringBootDemoOrmMybatisApplicationTests.java # 上下文加载测试基类 └── mapper/UserMapperTest.java # Mapper 功能测试从源码结构看该模块刻意保持精简一个实体、一个 Mapper 接口、一个 XML 文件覆盖了查询、插入、删除三类最典型的 CRUD 场景非常适合作为理解 Spring Boot 原生 MyBatis 整合原理的入门范例。pom.xml最小依赖组合模块的 pom.xml 中核心依赖是 MyBatis 官方 Starter版本通过属性统一管理properties java.version1.8/java.version mybatis.version1.3.2/mybatis.version /properties dependencies !-- MyBatis 官方 Spring Boot Starter自动装配 SqlSessionFactory 等核心 Bean -- dependency groupIdorg.mybatis.spring.boot/groupId artifactIdmybatis-spring-boot-starter/artifactId version${mybatis.version}/version /dependency !-- MySQL 驱动由父 POM 统一管理版本 -- dependency groupIdmysql/groupId artifactIdmysql-connector-java/artifactId /dependency !-- Lombok简化实体类的 getter/setter/构造器 -- dependency groupIdorg.projectlombok/groupId artifactIdlombok/artifactId optionaltrue/optional /dependency !-- Hutool 工具包测试中用于 UUID、MD5、日期等工具方法 -- dependency groupIdcn.hutool/groupId artifactIdhutool-all/artifactId /dependency !-- Guava 通用工具库 -- dependency groupIdcom.google.guava/groupId artifactIdguava/artifactId /dependency !-- Spring Boot 测试套件 -- dependency groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-test/artifactId scopetest/scope /dependency /dependencies各依赖的职责分工值得注意mybatis-spring-boot-starter是整个整合的枢纽它内部传递引入了mybatis、mybatis-spring以及 Spring Boot 自动配置相关模块只要 classpath 中存在它Spring Boot 就会在启动时自动创建SqlSessionFactory和SqlSessionTemplatemysql-connector-java不写版本号版本由根 pom.xml 中的依赖管理统一锁定这是多模块 Maven 工程的常见做法hutool-all与guava并非整合所必需主要用于测试代码中生成盐值、MD5 加密与集合断言减少手写工具代码。构建部分使用spring-boot-maven-plugin打包成可执行 JARfinalName指定为spring-boot-demo-orm-mybatis。启动类与 Mapper 扫描MapperScan 与 Mapper 的双保险SpringBootDemoOrmMybatisApplication.java 是标准的 Spring Boot 入口关键点在MapperScanMapperScan(basePackages {com.xkcoding.orm.mybatis.mapper}) SpringBootApplication public class SpringBootDemoOrmMybatisApplication { public static void main(String[] args) { SpringApplication.run(SpringBootDemoOrmMybatisApplication.class, args); } }MapperScan是 MyBatis-Spring 提供的注解作用是指定基础包路径由框架自动扫描该包及其子包下的所有 Mapper 接口并为每个接口生成动态代理对象注册到 Spring 容器。这样业务代码中就可以直接Autowired注入 Mapper 接口而无需逐个手动注册。与之配合UserMapper.java 接口上还同时标注了Mapper与ComponentMapper Component public interface UserMapper { ... }从代码结构可以推断作者采用了两层保险的策略Mapper是 MyBatis 层面的标记即便不写MapperScan只要接口标注了Mapper也能被识别注册Component则是 Spring 层面的通用组件标记确保该接口一定被纳入 Spring 的组件扫描。实际生产环境中二者选其一通常用MapperScanMapper组合即可正常运作双注解写法进一步降低了遗漏扫描的风险。application.yml数据源与 MyBatis 配置逐项解读application.yml 是整合配置的核心分为数据源、日志、MyBatis 三大部分。数据源配置spring: datasource: url: jdbc:mysql://127.0.0.1:3306/spring-boot-demo?useUnicodetruecharacterEncodingUTF-8useSSLfalseautoReconnecttruefailOverReadOnlyfalseserverTimezoneGMT%2B8 username: root password: root driver-class-name: com.mysql.cj.jdbc.Driver type: com.zaxxer.hikari.HikariDataSource initialization-mode: always continue-on-error: true schema: - classpath:db/schema.sql data: - classpath:db/data.sql hikari: minimum-idle: 5 connection-test-query: SELECT 1 FROM DUAL maximum-pool-size: 20 auto-commit: true idle-timeout: 30000 pool-name: SpringBootDemoHikariCP max-lifetime: 60000 connection-timeout: 30000逐项说明配置项值作用urljdbc:mysql://127.0.0.1:3306/spring-boot-demo?...连接地址serverTimezoneGMT%2B8即 GMT8解决 8.0 驱动时区问题useSSLfalse关闭 SSL 告警characterEncodingUTF-8保证中文不乱码driver-class-namecom.mysql.cj.jdbc.DriverMySQL 8.x 驱动的完整类名旧版是com.mysql.jdbc.Drivertypecom.zaxxer.hikari.HikariDataSource显式指定连接池类型为 HikariCPSpring Boot 2.x 的默认连接池initialization-mode: always—每次启动都执行初始化 SQL默认为 embedded 数据源才执行保证本地可重复跑通continue-on-error: true—初始化脚本执行出错时继续启动而非中断配合DROP TABLE IF EXISTS实现幂等初始化schemaclasspath:db/schema.sql启动时执行的建表脚本dataclasspath:db/data.sql启动时执行的初始化数据脚本HikariCP 连接池参数中minimum-idle5表示最小空闲连接数maximum-pool-size20表示最大连接数connection-test-query: SELECT 1 FROM DUAL是 MySQL 场景下测试连接可用性的探活 SQLOracle 风格的DUAL表在 MySQL 中同样可用max-lifetime60000限制连接最长存活 60 秒connection-timeout30000是获取连接的超时时间。MyBatis 核心配置mybatis: configuration: # 下划线转驼峰 map-underscore-to-camel-case: true mapper-locations: classpath:mappers/*.xml type-aliases-package: com.xkcoding.orm.mybatis.entitymap-underscore-to-camel-case: true开启数据库下划线命名到 Java 驼峰命名的自动映射。这是本模块最实用的配置之一——数据库字段是phone_number、create_time而实体属性是phoneNumber、createTime开启该配置后 MyBatis 的ResultMap自动完成映射无需为每个查询手写 resultMapmapper-locations: classpath:mappers/*.xml声明 XML 映射文件的扫描路径MyBatis 启动时会加载该路径下所有 XML 并解析其中的insert/delete/select/update节点type-aliases-package为指定包下的实体类注册类型别名。设置后在 XML 中可以用User简写替代全限定名com.xkcoding.orm.mybatis.entity.User。日志级别配置logging: level: com.xkcoding: debug com.xkcoding.orm.mybatis.mapper: trace将 Mapper 包日志级别调至trace可在运行测试时直接观察到 MyBatis 打印的完整 SQL 与绑定参数是本地排查 SQL 问题的有效手段。建表脚本与初始化数据schema.sql 定义orm_user表字段设计刻意使用了与 Java 属性不同的下划线命名用于验证驼峰映射配置DROP TABLE IF EXISTS orm_user; CREATE TABLE orm_user ( id INT(11) NOT NULL AUTO_INCREMENT PRIMARY KEY COMMENT 主键, name VARCHAR(32) NOT NULL UNIQUE COMMENT 用户名, password VARCHAR(32) NOT NULL COMMENT 加密后的密码, salt VARCHAR(32) NOT NULL COMMENT 加密使用的盐, email VARCHAR(32) NOT NULL UNIQUE COMMENT 邮箱, phone_number VARCHAR(15) NOT NULL UNIQUE COMMENT 手机号码, status INT(2) NOT NULL DEFAULT 1 COMMENT 状态-1逻辑删除0禁用1启用, create_time DATETIME NOT NULL DEFAULT NOW() COMMENT 创建时间, last_login_time DATETIME DEFAULT NULL COMMENT 上次登录时间, last_update_time DATETIME NOT NULL DEFAULT NOW() COMMENT 上次更新时间 ) ENGINEInnoDB DEFAULT CHARSETutf8 COMMENTSpring Boot Demo Orm 系列示例表;data.sql 预置了两条用户数据密码均为「明文密码 盐」的 MD5 值保证启动后即可直接查询验证INSERT INTO orm_user(id,name,password,salt,email,phone_number) VALUES (1, user_1, ff342e862e7c3285cdc07e56d6b8973b, 412365a109674b2dbb1981ed561a4c70, user1xkcoding.com, 17300000001); INSERT INTO orm_user(id,name,password,salt,email,phone_number) VALUES (2, user_2, 6c6bf02c8d5d3d128f34b1700cb1e32c, fcbdd0e8a9404a5585ea4e01d0e4d7a0, user2xkcoding.com, 17300000002);实体类Lombok 简化下的字段设计User.java 实现了Serializable接口并借助 Lombok 的Data、NoArgsConstructor、AllArgsConstructor、Builder四个注解自动生成 getter/setter、无参/全参构造器与建造者模式方法Data NoArgsConstructor AllArgsConstructor Builder public class User implements Serializable { private static final long serialVersionUID -1840831686851699943L; private Long id; // 主键 private String name; // 用户名 private String password; // 加密后的密码 private String salt; // 加密使用的盐 private String email; // 邮箱 private String phoneNumber; // 手机号码 private Integer status; // 状态-1逻辑删除0禁用1启用 private Date createTime; // 创建时间 private Date lastLoginTime; // 上次登录时间 private Date lastUpdateTime; // 上次更新时间 }注意status字段的注释约定-1 逻辑删除、0 禁用、1 启用这是一种典型的软删除设计预留——本模块的deleteById采用的是物理删除但字段设计上已为逻辑删除留出余地。Mapper 的两种写法注解 SQL 与 XML 映射混用本模块最有教学价值的点在于 UserMapper.java 同时示范了 MyBatis 的两种 SQL 组织方式。注解式 SQL查询查询方法直接通过Select注解内联 SQL适合简单、固定的查询Select(SELECT * FROM orm_user) ListUser selectAllUser(); Select(SELECT * FROM orm_user WHERE id #{id}) User selectUserById(Param(id) Long id);#{id}是 MyBatis 的预编译占位符最终会以?的形式进入 JDBCPreparedStatement天然防止 SQL 注入。当方法只有一个参数时XML 或注解中直接使用#{id}即可当参数为对象时则通过Param(user)为参数命名XML 中以#{user.xxx}的形式引用对象的属性。XML 映射写操作复杂或需要动态 SQL 的语句更适合放入 XML。UserMapper.xml 中实现了插入与删除?xml version1.0 encodingUTF-8? !DOCTYPE mapper PUBLIC -//mybatis.org//DTD Mapper 3.0//EN http://mybatis.org/dtd/mybatis-3-mapper.dtd mapper namespacecom.xkcoding.orm.mybatis.mapper.UserMapper insert idsaveUser INSERT INTO orm_user (name, password, salt, email, phone_number, status, create_time, last_login_time, last_update_time) VALUES (#{user.name}, #{user.password}, #{user.salt}, #{user.email}, #{user.phoneNumber}, #{user.status}, #{user.createTime}, #{user.lastLoginTime}, #{user.lastUpdateTime}) /insert delete iddeleteById DELETE FROM orm_user WHERE id #{id} /delete /mapper两个关键点namespace必须与 Mapper 接口的全限定名一致MyBatis 通过它建立 XML 节点与接口方法的绑定关系insert与delete节点的id必须与接口方法名一致saveUser对应saveUser(Param(user) User user)deleteById对应deleteById(Param(id) Long id)。此时接口方法上不需要再写Insert/Delete注解XML 中的语句会自动生效。关于#{user.phoneNumber}这类引用能够正确命中phone_number列正是得益于map-underscore-to-camel-case的开启——当然在INSERT语句中列是显式写出的驼峰映射主要体现在SELECT *查询结果到实体属性的自动赋值上。这种「查询走注解、写操作走 XML」的混用方式体现了 MyBatis 两种 SQL 组织方式的取舍注解适合简短固定 SQLXML 则对动态 SQLif、foreach、where等和复杂结果映射支持更完善且无需重新编译 Java 代码即可调整 SQL。单元测试验证 Mapper 全链路可用测试分为基类与功能测试两层。SpringBootDemoOrmMybatisApplicationTests.java 通过SpringBootTest加载完整 Spring 上下文并提供一个空的contextLoads()用例验证应用能否正常启动、MyBatis 相关 Bean 能否装配成功RunWith(SpringRunner.class) SpringBootTest public class SpringBootDemoOrmMybatisApplicationTests { Test public void contextLoads() { } }UserMapperTest.java 继承该基类直接Autowired注入UserMapper进行四个 CRUD 断言测试Slf4j public class UserMapperTest extends SpringBootDemoOrmMybatisApplicationTests { Autowired private UserMapper userMapper; /** 查询所有用户断言集合非空 */ Test public void selectAllUser() { ListUser userList userMapper.selectAllUser(); Assert.assertTrue(CollUtil.isNotEmpty(userList)); log.debug(【userList】 {}, userList); } /** 根据主键查询断言非空 */ Test public void selectUserById() { User user userMapper.selectUserById(1L); Assert.assertNotNull(user); log.debug(【user】 {}, user); } /** 保存用户MD5 加盐加密后入库断言影响行数为 1 */ Test public void saveUser() { String salt IdUtil.fastSimpleUUID(); User user User.builder() .name(testSave3) .password(SecureUtil.md5(123456 salt)) .salt(salt) .email(testSave3xkcoding.com) .phoneNumber(17300000003) .status(1) .lastLoginTime(new DateTime()) .createTime(new DateTime()) .lastUpdateTime(new DateTime()) .build(); int i userMapper.saveUser(user); Assert.assertEquals(1, i); } /** 根据主键删除断言影响行数为 1 */ Test public void deleteById() { int i userMapper.deleteById(1L); Assert.assertEquals(1, i); } }测试代码中值得借鉴的细节密码安全实践saveUser测试使用IdUtil.fastSimpleUUID()生成随机盐再用SecureUtil.md5(123456 salt)计算加盐 MD5 后入库与salt字段配合是「密码不以明文落库」的典型示范参数绑定验证XML 中的#{user.xxx}嵌套属性引用正是通过测试中的User.builder()构造的完整对象来验证的返回约定saveUser、deleteById返回int即 SQL 影响的行数断言等于 1 即证明写入或删除成功。运行与验证方式由于initialization-mode: always会在启动时自动执行 schema.sql 与 data.sql本地只需准备一个 MySQL 实例并按 application.yml 调整连接信息默认127.0.0.1:3306、库名spring-boot-demo、账号密码root/root即可按以下方式运行验证# 在仓库根目录构建并运行测试 mvn -pl demo-orm-mybatis -am test # 或打包后直接运行 mvn -pl demo-orm-mybatis -am package java -jar demo-orm-mybatis/target/spring-boot-demo-orm-mybatis.jar运行测试时将com.xkcoding.orm.mybatis.mapper日志级别调为trace配置已就绪控制台即可输出 MyBatis 执行的完整 SQL 与参数便于观察预编译占位符的实际替换过程。小结通过本模块可以提炼出 Spring Boot 整合原生 MyBatis 的四步标准流程引依赖引入mybatis-spring-boot-starter版本 1.3.2见 pom.xml配数据源在 application.yml 中配置 JDBC 连接与 HikariCP 连接池定扫描启动类声明MapperScan或在 Mapper 接口上标注Mapper写映射注解Select负责查询XML 文件负责写操作二者通过namespaceid与接口方法绑定。整套方案完全依赖 MyBatis 官方 Starter 的自动装配无需手写任何SqlSessionFactory配置代码是 Spring Boot 项目中使用原生 MyBatis 的标准姿势。若需要对比其他 ORM 方案可参考仓库中同系列的 demo-orm-jpa、demo-orm-mybatis-plus 与 demo-orm-jdbctemplate 等模块进一步理解不同持久层框架的适用场景。【免费下载链接】spring-boot-demo一个用来深入学习并实战 Spring Boot 的项目。项目地址: https://gitcode.com/gh_mirrors/sp/spring-boot-demo创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考