Spring Boot 整合 MyBatis:从入门到企业级实践
一、整合优势:为什么 Spring Boot+MyBatis 成为主流组合?
Spring Boot 以其 "约定优于配置" 的理念,极大简化了 Spring 应用的开发流程;而 MyBatis 则以其灵活的 SQL 控制能力,在持久层框架中占据重要地位。两者的结合带来了以下优势:
- 简化配置:消除大量 XML 配置,通过注解和少量配置即可完成整合
- 开发高效:自动配置减少样板代码,专注业务逻辑实现
- 生态完善:Spring Boot 的自动配置与 MyBatis 的插件体系无缝衔接
- 易于扩展:支持自定义配置和高级特性
- 企业认可:广泛应用于生产环境,社区活跃,问题解决方案丰富
本文将详细介绍 Spring Boot 整合 MyBatis 的完整流程,从基础配置到高级特性,再到企业级最佳实践,帮助你快速掌握这一主流技术组合。
二、环境准备与基础配置
2.1 技术栈选择
- Spring Boot:2.7.x(稳定版本)
- MyBatis:3.5.x
- 数据库:MySQL 8.0
- 构建工具:Maven
- 开发工具:IntelliJ IDEA
2.2 创建项目与依赖配置
创建 Spring Boot 项目,在pom.xml
中添加以下依赖:
xml
<dependencies><!-- Spring Boot Web --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><!-- MyBatis整合Spring Boot --><dependency><groupId>org.mybatis.spring.boot</groupId><artifactId>mybatis-spring-boot-starter</artifactId><version>2.3.2</version></dependency><!-- MySQL驱动 --><dependency><groupId>com.mysql</groupId><artifactId>mysql-connector-j</artifactId><scope>runtime</scope></dependency><!-- lombok(简化实体类) --><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><optional>true</optional></dependency><!-- 测试 --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency>
</dependencies>
2.3 数据库配置
在application.yml
中配置数据库连接信息:
yaml
spring:datasource:driver-class-name: com.mysql.cj.jdbc.Driverurl: jdbc:mysql://localhost:3306/mybatis_demo?serverTimezone=UTC&useSSL=false&characterEncoding=utf8username: rootpassword: root# 连接池配置(Spring Boot 2.0+默认使用HikariCP)hikari:maximum-pool-size: 10 # 最大连接数minimum-idle: 5 # 最小空闲连接idle-timeout: 300000 # 空闲超时时间(5分钟)connection-timeout: 20000 # 连接超时时间(20秒)
2.4 MyBatis 基础配置
yaml
mybatis:# Mapper XML文件位置mapper-locations: classpath:mapper/**/*.xml# 实体类包路径(用于别名)type-aliases-package: com.example.pojo# 配置项configuration:map-underscore-to-camel-case: true # 开启驼峰命名映射log-impl: org.apache.ibatis.logging.stdout.StdOutImpl # 日志实现cache-enabled: true # 开启二级缓存lazy-loading-enabled: false # 关闭延迟加载
三、基础整合实现:注解与 XML 两种方式
Spring Boot 整合 MyBatis 支持两种开发方式:纯注解方式和 XML 映射方式,可根据项目需求选择。
3.1 纯注解方式
适用于 SQL 语句简单的场景,无需 XML 文件。
3.1.1 实体类
java
运行
package com.example.pojo;import lombok.Data;@Data // Lombok注解,自动生成Getter、Setter、toString等
public class User {private Integer id;private String username;private String password;private Integer age;private String email;
}
3.1.2 Mapper 接口
java
运行
package com.example.mapper;import com.example.pojo.User;
import org.apache.ibatis.annotations.*;
import java.util.List;// @Mapper注解:标识这是MyBatis的Mapper接口
@Mapper
public interface UserMapper {// 查询所有用户@Select("SELECT * FROM user")List<User> getAllUsers();// 根据ID查询@Select("SELECT * FROM user WHERE id = #{id}")User getUserById(Integer id);// 添加用户@Insert("INSERT INTO user(username, password, age, email) " +"VALUES(#{username}, #{password}, #{age}, #{email})")@Options(useGeneratedKeys = true, keyProperty = "id") // 返回自增IDint addUser(User user);// 更新用户@Update("UPDATE user SET username = #{username}, password = #{password}, " +"age = #{age}, email = #{email} WHERE id = #{id}")int updateUser(User user);// 删除用户@Delete("DELETE FROM user WHERE id = #{id}")int deleteUser(Integer id);
}
3.1.3 Service 层
java
运行
package com.example.service;import com.example.pojo.User;
import java.util.List;public interface UserService {List<User> getAllUsers();User getUserById(Integer id);int addUser(User user);int updateUser(User user);int deleteUser(Integer id);
}
java
运行
package com.example.service.impl;import com.example.mapper.UserMapper;
import com.example.pojo.User;
import com.example.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;@Service
public class UserServiceImpl implements UserService {@Autowiredprivate UserMapper userMapper;@Overridepublic List<User> getAllUsers() {return userMapper.getAllUsers();}@Overridepublic User getUserById(Integer id) {return userMapper.getUserById(id);}@Overridepublic int addUser(User user) {return userMapper.addUser(user);}@Overridepublic int updateUser(User user) {return userMapper.updateUser(user);}@Overridepublic int deleteUser(Integer id) {return userMapper.deleteUser(id);}
}
3.1.4 Controller 层
java
运行
package com.example.controller;import com.example.pojo.User;
import com.example.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.util.List;@RestController
@RequestMapping("/users")
public class UserController {@Autowiredprivate UserService userService;@GetMappingpublic List<User> getAllUsers() {return userService.getAllUsers();}@GetMapping("/{id}")public User getUserById(@PathVariable Integer id) {return userService.getUserById(id);}@PostMappingpublic String addUser(@RequestBody User user) {int rows = userService.addUser(user);return rows > 0 ? "添加成功,ID:" + user.getId() : "添加失败";}@PutMappingpublic String updateUser(@RequestBody User user) {int rows = userService.updateUser(user);return rows > 0 ? "更新成功" : "更新失败";}@DeleteMapping("/{id}")public String deleteUser(@PathVariable Integer id) {int rows = userService.deleteUser(id);return rows > 0 ? "删除成功" : "删除失败";}
}
3.2 XML 映射方式
适用于 SQL 语句复杂的场景,将 SQL 与 Java 代码分离。
3.2.1 创建 Mapper 接口
java
运行
package com.example.mapper;import com.example.pojo.User;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import java.util.List;
import java.util.Map;@Mapper
public interface UserXmlMapper {List<User> getAllUsers();User getUserById(Integer id);int addUser(User user);int updateUser(User user);int deleteUser(Integer id);// 复杂查询示例List<User> queryUserByCondition(@Param("params") Map<String, Object> params);
}
3.2.2 创建 XML 映射文件
在src/main/resources/mapper
目录下创建UserXmlMapper.xml
:
xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""https://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.example.mapper.UserXmlMapper"><select id="getAllUsers" resultType="User">SELECT * FROM user</select><select id="getUserById" parameterType="int" resultType="User">SELECT * FROM user WHERE id = #{id}</select><insert id="addUser" parameterType="User" useGeneratedKeys="true" keyProperty="id">INSERT INTO user(username, password, age, email)VALUES(#{username}, #{password}, #{age}, #{email})</insert><update id="updateUser" parameterType="User">UPDATE userSET username = #{username}, password = #{password},age = #{age}, email = #{email}WHERE id = #{id}</update><delete id="deleteUser" parameterType="int">DELETE FROM user WHERE id = #{id}</delete><!-- 复杂查询示例 --><select id="queryUserByCondition" resultType="User">SELECT * FROM user<where><if test="params.username != null and params.username != ''">AND username LIKE CONCAT('%', #{params.username}, '%')</if><if test="params.minAge != null">AND age >= #{params.minAge}</if><if test="params.maxAge != null">AND age <= #{params.maxAge}</if></where></select>
</mapper>
3.2.3 启动类配置
需要在启动类上添加@MapperScan
注解扫描 Mapper 接口:
java
运行
package com.example;import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;@SpringBootApplication
// 扫描Mapper接口所在的包
@MapperScan("com.example.mapper")
public class MybatisSpringbootDemoApplication {public static void main(String[] args) {SpringApplication.run(MybatisSpringbootDemoApplication.class, args);}
}
四、高级特性:分页、事务与逆向工程
4.1 分页查询实现
使用 MyBatis 分页插件pagehelper
实现分页功能。
4.1.1 添加依赖
xml
<dependency><groupId>com.github.pagehelper</groupId><artifactId>pagehelper-spring-boot-starter</artifactId><version>1.4.6</version>
</dependency>
4.1.2 分页配置
yaml
pagehelper:helper-dialect: mysql # 指定数据库方言reasonable: true # 合理化分页support-methods-arguments: true # 支持方法参数分页params: count=countSql # 计数参数
4.1.3 分页查询实现
java
运行
// Service层
@Override
public PageInfo<User> getUserByPage(int pageNum, int pageSize) {// 分页插件会自动拦截并处理下面的查询PageHelper.startPage(pageNum, pageSize);List<User> users = userXmlMapper.getAllUsers();// 封装分页信息return new PageInfo<>(users);
}// Controller层
@GetMapping("/page")
public PageInfo<User> getUserByPage(@RequestParam(defaultValue = "1") int pageNum,@RequestParam(defaultValue = "10") int pageSize) {return userService.getUserByPage(pageNum, pageSize);
}
4.2 事务管理
Spring Boot 提供了声明式事务管理,通过@Transactional
注解实现。
4.2.1 事务配置
java
运行
// 在启动类或配置类上添加@EnableTransactionManagement(可选,Spring Boot默认开启)
@SpringBootApplication
@MapperScan("com.example.mapper")
@EnableTransactionManagement
public class MybatisSpringbootDemoApplication { ... }
4.2.2 事务使用示例
java
运行
@Service
public class UserServiceImpl implements UserService {// ...其他代码// 声明式事务@Transactional(rollbackFor = Exception.class)@Overridepublic void batchOperation() {// 操作1User user = new User("test", "123", 20, "test@example.com");userMapper.addUser(user);// 模拟异常int i = 1 / 0;// 操作2(如果发生异常,此操作会回滚)userMapper.deleteUser(1);}
}
事务属性说明:
rollbackFor
:指定需要回滚的异常类型propagation
:事务传播行为(默认 REQUIRED)isolation
:事务隔离级别(默认 DEFAULT)readOnly
:是否只读事务(查询操作建议设置为 true)timeout
:事务超时时间
4.3 MyBatis 逆向工程
使用 MyBatis Generator 自动生成实体类、Mapper 接口和 XML 文件。
4.3.1 添加依赖
xml
<plugin><groupId>org.mybatis.generator</groupId><artifactId>mybatis-generator-maven-plugin</artifactId><version>1.4.2</version><configuration><configurationFile>src/main/resources/generatorConfig.xml</configurationFile><overwrite>true</overwrite><verbose>true</verbose></configuration>
</plugin>
4.3.2 创建配置文件
在src/main/resources
下创建generatorConfig.xml
:
xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE generatorConfigurationPUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN""https://mybatis.org/dtd/mybatis-generator-config_1_0.dtd"><generatorConfiguration><!-- 数据库驱动 --><classPathEntry location="C:\Users\yourname\.m2\repository\com\mysql\mysql-connector-j\8.0.33\mysql-connector-j-8.0.33.jar"/><context id="MySQLContext" targetRuntime="MyBatis3"><!-- 生成toString()方法 --><plugin type="org.mybatis.generator.plugins.ToStringPlugin"/><!-- 数据库连接信息 --><jdbcConnection driverClass="com.mysql.cj.jdbc.Driver"connectionURL="jdbc:mysql://localhost:3306/mybatis_demo?serverTimezone=UTC"userId="root"password="root"></jdbcConnection><!-- 生成模型的包名和位置 --><javaModelGenerator targetPackage="com.example.pojo"targetProject="src/main/java"><property name="enableSubPackages" value="true"/><property name="trimStrings" value="true"/></javaModelGenerator><!-- 生成Mapper XML的包名和位置 --><sqlMapGenerator targetPackage="mapper"targetProject="src/main/resources"><property name="enableSubPackages" value="true"/></sqlMapGenerator><!-- 生成Mapper接口的包名和位置 --><javaClientGenerator type="XMLMAPPER"targetPackage="com.example.mapper"targetProject="src/main/java"><property name="enableSubPackages" value="true"/></javaClientGenerator><!-- 要生成的表 --><table tableName="user" domainObjectName="User"enableCountByExample="false" enableUpdateByExample="false"enableDeleteByExample="false" enableSelectByExample="false"selectByExampleQueryId="false"></table></context>
</generatorConfiguration>
4.3.3 执行生成命令
bash
mvn mybatis-generator:generate
五、企业级实践:性能优化与安全考量
5.1 性能优化策略
连接池优化:
- 合理设置连接池大小(根据 CPU 核心数和并发量)
- 配置适当的超时时间
SQL 优化:
- 避免
SELECT *
,只查询需要的字段 - 合理使用索引
- 复杂查询拆分或使用存储过程
- 避免
缓存策略:
- 开启二级缓存,合理设置缓存参数
- 集成 Redis 实现分布式缓存
- 对热点数据进行缓存
批量操作优化:
- 使用
foreach
标签进行批量插入 / 更新 - 大批次操作分阶段执行,避免内存溢出
- 使用
延迟加载:
- 对关联查询启用延迟加载,减少不必要的数据查询
xml
<setting name="lazyLoadingEnabled" value="true"/> <setting name="aggressiveLazyLoading" value="false"/>
5.2 安全考量
防止 SQL 注入:
- 使用
#{}
而非${}
- 必须使用
${}
时进行白名单校验
- 使用
输入验证:
- 对所有用户输入进行验证和过滤
- 使用参数绑定而非字符串拼接
敏感数据保护:
- 密码加密存储(如使用 BCrypt)
- 传输过程中使用 HTTPS
- 敏感字段脱敏展示
权限控制:
- 实现基于角色的访问控制(RBAC)
- 对数据库操作进行权限校验
日志与审计:
- 记录关键操作日志
- 实现数据库操作审计机制
六、常见问题与解决方案
Mapper 接口注入失败:
- 检查是否添加
@Mapper
注解或@MapperScan
配置 - 确保接口名称与 XML 文件的
namespace
一致
- 检查是否添加
XML 映射文件找不到:
- 检查
mapper-locations
配置是否正确 - 确保 XML 文件在
resources
目录下,且路径正确 - 检查 Maven 配置,确保资源文件被正确打包
- 检查
事务不回滚:
- 检查是否抛出了
unchecked
异常(默认只回滚 RuntimeException) - 确认
@Transactional
注解是否添加在 public 方法上 - 检查异常是否被 try-catch 捕获而未重新抛出
- 检查是否抛出了
分页插件不生效:
- 确保
PageHelper.startPage()
在查询方法之前调用 - 检查分页插件依赖是否正确添加
- 确认数据库方言配置正确
- 确保
驼峰命名映射不生效:
- 检查
map-underscore-to-camel-case
是否设置为true
- 确保实体类属性名与数据库字段名符合驼峰规则
- 检查
总结
Spring Boot 整合 MyBatis 为 Java 持久层开发提供了高效、灵活的解决方案。本文从基础配置到高级特性,全面介绍了两者的整合过程,包括注解与 XML 两种开发方式、分页实现、事务管理和逆向工程等关键技术点。
在企业级实践中,还需要关注性能优化和安全问题,合理使用缓存、连接池和事务管理,确保系统的高效稳定运行。通过掌握这些知识,你可以快速构建出高质量的数据库访问层,为业务逻辑提供可靠支持。
Spring Boot 与 MyBatis 的组合仍然是当前 Java 开发的主流选择之一,持续深入学习和实践这一技术栈,将为你的职业发展带来重要价值。