1. SpringBoot与MyBatis整合实战:从基础到高效开发
作为一名长期奋战在一线的Java开发者,我深知MyBatis在持久层框架中的重要地位。今天要分享的是SpringBoot整合MyBatis的完整实践方案,重点解决两个实际开发中的痛点:分页处理和重复CRUD代码编写。这个方案已经在我们团队的多个项目中得到验证,能显著提升开发效率。
2. 环境准备与基础配置
2.1 数据库环境搭建
我们先从MySQL数据库准备开始。创建测试数据库和用户表结构:
sql复制CREATE DATABASE IF NOT EXISTS java_diary;
USE java_diary;
CREATE TABLE IF NOT EXISTS t_user (
id INT PRIMARY KEY AUTO_INCREMENT COMMENT '用户ID',
username VARCHAR(50) NOT NULL COMMENT '用户名',
password VARCHAR(100) COMMENT '密码',
age INT COMMENT '年龄',
email VARCHAR(100) COMMENT '邮箱',
create_time DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间'
) COMMENT = '用户信息表';
-- 插入5条测试数据
INSERT INTO t_user (username, password, age, email) VALUES
('zhangsan', '123456', 20, 'zhangsan@test.com'),
('lisi', '654321', 22, 'lisi@test.com'),
('wangwu', '987654', 25, 'wangwu@test.com'),
('zhaoliu', '111111', 18, 'zhaoliu@test.com'),
('qianqi', '222222', 30, 'qianqi@test.com');
这个表结构设计考虑了常见用户信息的存储需求,包含基础字段和创建时间。create_time字段设置为DEFAULT CURRENT_TIMESTAMP,这样插入记录时会自动填充当前时间。
2.2 Maven依赖配置
在pom.xml中添加必要的依赖项:
xml复制<dependencies>
<!-- SpringBoot Web核心 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- MySQL驱动 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<!-- MyBatis整合SpringBoot -->
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.3.0</version>
</dependency>
<!-- 分页插件PageHelper -->
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper-spring-boot-starter</artifactId>
<version>1.4.6</version>
</dependency>
<!-- lombok简化代码 -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
</dependencies>
<!-- MyBatis代码生成器插件 -->
<build>
<plugins>
<plugin>
<groupId>org.mybatis.generator</groupId>
<artifactId>mybatis-generator-maven-plugin</artifactId>
<version>1.4.2</version>
<dependencies>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.33</version>
</dependency>
</dependencies>
</plugin>
</plugins>
</build>
这里有几个关键点需要注意:
- mybatis-spring-boot-starter版本要与SpringBoot版本匹配
- pagehelper-spring-boot-starter已经包含了PageHelper核心依赖
- MySQL驱动版本建议与数据库服务端版本保持一致
2.3 应用配置文件
application.yml配置内容:
yaml复制spring:
datasource:
url: jdbc:mysql://localhost:3306/java_diary?useUnicode=true&characterEncoding=utf8&useSSL=false&serverTimezone=Asia/Shanghai
username: root
password: root
driver-class-name: com.mysql.cj.jdbc.Driver
mybatis:
mapper-locations: classpath:mapper/*.xml
type-aliases-package: com.java.diary.entity
configuration:
map-underscore-to-camel-case: true
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
pagehelper:
helper-dialect: mysql
reasonable: true
support-methods-arguments: true
配置说明:
- map-underscore-to-camel-case开启后,数据库字段create_time会自动映射到Java属性createTime
- pagehelper.reasonable=true时,当页码超出范围会自动修正到合理值
- 开发环境建议开启SQL日志(mybatis.configuration.log-impl)方便调试
3. 基础整合实现
3.1 实体类设计
使用Lombok简化代码:
java复制@Data
public class User {
private Integer id;
private String username;
private String password;
private Integer age;
private String email;
private LocalDateTime createTime;
}
@Data注解会自动生成getter/setter、toString等方法。LocalDateTime类型比传统的Date更现代,提供了更好的API支持。
3.2 Mapper接口定义
java复制@Mapper
public interface UserMapper {
List<User> findAll();
User findById(Integer id);
int insert(User user);
int update(User user);
int delete(Integer id);
}
@Mapper注解标记这是一个MyBatis映射接口,Spring会自动为其创建实现类。接口方法名与XML中的SQL语句id对应。
3.3 XML映射文件
src/main/resources/mapper/UserMapper.xml内容:
xml复制<mapper namespace="com.java.diary.mapper.UserMapper">
<resultMap id="UserResultMap" type="User">
<id column="id" property="id"/>
<result column="username" property="username"/>
<result column="password" property="password"/>
<result column="age" property="age"/>
<result column="email" property="email"/>
<result column="create_time" property="createTime"/>
</resultMap>
<select id="findAll" resultMap="UserResultMap">
SELECT * FROM t_user
</select>
<insert id="insert" parameterType="User" useGeneratedKeys="true" keyProperty="id">
INSERT INTO t_user (username, password, age, email)
VALUES (#{username}, #{password}, #{age}, #{email})
</insert>
</mapper>
关键点:
- useGeneratedKeys="true" keyProperty="id" 用于获取自增主键
- #{}是MyBatis的参数占位符,会进行预编译防止SQL注入
- resultMap虽然可以省略(开启驼峰映射后),但显式定义更清晰
3.4 分页功能实现
Service层实现分页查询:
java复制@Service
public class UserServiceImpl implements UserService {
@Resource
private UserMapper userMapper;
@Override
public List<User> findByPage(Integer pageNum, Integer pageSize) {
PageHelper.startPage(pageNum, pageSize);
return userMapper.findAll();
}
}
PageHelper.startPage()必须在查询方法前调用,且要紧邻查询语句。Controller返回分页信息:
java复制@GetMapping("/page")
public Map<String, Object> findByPage(
@RequestParam(defaultValue = "1") Integer pageNum,
@RequestParam(defaultValue = "10") Integer pageSize) {
List<User> userList = userService.findByPage(pageNum, pageSize);
PageInfo<User> pageInfo = new PageInfo<>(userList);
Map<String, Object> result = new HashMap<>();
result.put("code", 200);
result.put("data", pageInfo);
return result;
}
PageInfo包含了丰富的分页信息:
- pageNum: 当前页
- pageSize: 每页数量
- total: 总记录数
- pages: 总页数
- list: 当前页数据列表
4. MyBatis代码生成器高级用法
4.1 生成器配置
src/main/resources/generatorConfig.xml配置:
xml复制<generatorConfiguration>
<context id="MySQLContext" targetRuntime="MyBatis3">
<!-- 数据库连接配置 -->
<jdbcConnection driverClass="com.mysql.cj.jdbc.Driver"
connectionURL="jdbc:mysql://localhost:3306/java_diary"
userId="root"
password="root">
</jdbcConnection>
<!-- 生成模型 -->
<javaModelGenerator targetPackage="com.java.diary.entity"
targetProject="src/main/java">
<property name="enableSubPackages" value="true"/>
</javaModelGenerator>
<!-- 生成Mapper接口 -->
<javaClientGenerator type="XMLMAPPER"
targetPackage="com.java.diary.mapper"
targetProject="src/main/java">
<property name="enableSubPackages" value="true"/>
</javaClientGenerator>
<!-- 指定表 -->
<table tableName="t_user" domainObjectName="User">
<generatedKey column="id" sqlStatement="MySQL" identity="true"/>
</table>
</context>
</generatorConfiguration>
4.2 生成代码执行
运行生成命令:
bash复制mvn mybatis-generator:generate
生成的文件包括:
- User.java实体类
- UserMapper.java接口
- UserMapper.xml映射文件
4.3 生成代码优化建议
默认生成的代码可能需要调整:
- 实体类添加Lombok注解
- 移除Example查询方法(简化代码)
- 调整XML中的resultMap定义
- 添加自定义的查询方法
5. 实战问题排查指南
5.1 分页不生效常见原因
- PageHelper.startPage()调用位置不对,必须紧邻查询语句
- 依赖冲突,检查是否引入了多个PageHelper版本
- 分页插件配置未生效,检查application.yml配置
- 查询方法被AOP代理,导致PageHelper拦截失效
5.2 代码生成器常见错误
- 数据库连接失败:检查用户名密码、网络连接
- 驱动类找不到:确认mysql-connector-java版本
- 生成文件被锁定:关闭IDE或解除文件锁定
- 表不存在:检查tableName拼写是否正确
5.3 性能优化建议
- 分页查询大数据量表时,使用PageHelper的count查询优化
- 复杂查询考虑添加二级缓存
- 批量操作使用BatchExecutor
- 合理配置连接池参数(如HikariCP)
6. 扩展思考与进阶方向
掌握了基础整合后,可以进一步研究:
- MyBatis动态SQL的灵活应用
- 自定义TypeHandler处理特殊类型
- 插件开发实现审计日志等功能
- 多数据源配置方案
- MyBatis与JPA的混合使用
在实际项目中,我们通常会根据业务复杂度选择不同的实现方案。对于简单CRUD,代码生成器能极大提升效率;复杂业务逻辑则需要精心设计Mapper和XML映射。分页插件虽然方便,但在处理百万级数据时需要特别注意性能优化。