目录
- 引言
- Spring Boot 基础回顾
- MyBatis 核心概念解析
- Spring Boot 整合 MyBatis
- MyBatis 高级特性
- Spring Boot + MyBatis 最佳实践
- 性能优化与扩展
- 实战案例:电商系统开发
- 常见问题与解决方案
- 总结与展望
1. 引言
1.1 技术背景与现状
在现代企业级应用开发中,数据持久化是一个核心需求。随着Java生态系统的不断发展,出现了多种ORM框架,如Hibernate、MyBatis、JPA等。其中,MyBatis因其灵活性、高性能和易用性,在企业级应用中占据了重要地位。
Spring Boot作为Spring框架的"约定优于配置"实现,极大地简化了Spring应用的初始搭建和开发过程。将Spring Boot与MyBatis结合,可以充分发挥两者的优势,构建高效、可维护的数据访问层。
1.2 为什么选择Spring Boot + MyBatis
- 开发效率高:Spring Boot的自动配置和起步依赖大大减少了样板代码
- 灵活性好:MyBatis允许开发者直接编写SQL,保持了对SQL的完全控制
- 性能优异:MyBatis避免了Hibernate等框架可能产生的复杂查询问题
- 易于集成:Spring Boot对MyBatis有良好的官方支持
- 生态丰富:两者都有庞大的社区和丰富的插件支持
1.3 本文内容概览
本文将全面介绍Spring Boot与MyBatis的整合与实践,从基础配置到高级特性,再到性能优化和实战案例,为开发者提供一站式解决方案。
2. Spring Boot 基础回顾
2.1 Spring Boot 核心特性
Spring Boot的核心设计理念是"约定优于配置",其主要特性包括:
- 自动配置:根据classpath中的jar包自动配置Spring应用
- 起步依赖:简化Maven/Gradle配置,一键式添加功能模块
- Actuator:提供生产级监控和管理端点
- 嵌入式容器:内置Tomcat、Jetty等Servlet容器
- 外部化配置:支持多种格式的配置文件和环境变量
2.2 Spring Boot 项目结构
标准的Spring Boot项目结构如下:
src/
├── main/
│ ├── java/
│ │ └── com/
│ │ └── example/
│ │ └── demo/
│ │ ├── DemoApplication.java # 启动类
│ │ ├── config/ # 配置类
│ │ ├── controller/ # 控制器
│ │ ├── service/ # 服务层
│ │ ├── dao/ # 数据访问层
│ │ └── model/ # 实体类
│ └── resources/
│ ├── static/ # 静态资源
│ ├── templates/ # 模板文件
│ ├── application.yml # 主配置文件
│ └── mapper/ # MyBatis映射文件
└── test/ # 测试代码
2.3 Spring Boot 自动配置原理
Spring Boot的自动配置是通过@EnableAutoConfiguration注解实现的,其核心机制包括:
- 条件注解:如
@ConditionalOnClass、@ConditionalOnMissingBean等 - 自动配置类:位于
META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports - 配置属性:通过
@ConfigurationProperties绑定外部配置
示例:查看自动配置报告
# 启用debug日志查看自动配置报告
logging.level.root=debug
或者在启动时添加--debug参数:
java -jar myapp.jar --debug
3. MyBatis 核心概念解析
3.1 MyBatis 架构概述
MyBatis的整体架构分为三层:
- 基础支撑层:事务管理、连接池、缓存、日志等基础设施
- 核心处理层:配置解析、参数映射、SQL解析、SQL执行、结果集映射
- 接口层:SqlSession API、Mapper接口
3.2 核心组件详解
3.2.1 SqlSessionFactory
SqlSessionFactory是MyBatis的核心对象,用于创建SqlSession。通常一个应用只需要一个SqlSessionFactory实例。
构建方式:
String resource = "mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
3.2.2 SqlSession
SqlSession代表一次数据库会话,线程不安全,每次使用后应该关闭。主要方法包括:
selectOne():查询单个对象selectList():查询对象列表insert():插入数据update():更新数据delete():删除数据commit():提交事务rollback():回滚事务
3.2.3 Mapper 接口
Mapper接口是MyBatis的核心概念之一,通过动态代理技术将接口方法与SQL语句绑定。示例:
public interface UserMapper {@Select("SELECT * FROM users WHERE id = #{id}")User selectUser(int id);
}
3.3 XML 映射文件
MyBatis的XML映射文件包含以下主要元素:
<select>:查询语句<insert>:插入语句<update>:更新语句<delete>:删除语句<sql>:可重用的SQL片段<resultMap>:结果集映射
示例:
<mapper namespace="com.example.mapper.UserMapper"><resultMap id="userResultMap" type="User"><id property="id" column="id"/><result property="username" column="username"/><result property="email" column="email"/></resultMap><select id="selectUser" resultMap="userResultMap">SELECT * FROM users WHERE id = #{id}</select>
</mapper>
3.4 动态SQL
MyBatis提供了强大的动态SQL功能,主要元素包括:
<if>:条件判断<choose>/<when>/<otherwise>:多条件选择<trim>/<where>/<set>:辅助处理SQL片段<foreach>:循环遍历集合
示例:
<select id="findUsers" resultType="User">SELECT * FROM users<where><if test="username != null">AND username like #{username}</if><if test="email != null">AND email = #{email}</if></where>
</select>
4. Spring Boot 整合 MyBatis
4.1 项目初始化
4.1.1 使用Spring Initializr创建项目
可以通过https://start.spring.io或IDE插件创建Spring Boot项目,添加以下依赖:
- Spring Web
- MyBatis Framework
- MySQL Driver (或其他数据库驱动)
- Lombok (可选,简化代码)
4.1.2 Maven依赖配置
<dependencies><!-- Spring Boot Starter --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><!-- MyBatis Starter --><dependency><groupId>org.mybatis.spring.boot</groupId><artifactId>mybatis-spring-boot-starter</artifactId><version>3.0.3</version></dependency><!-- MySQL Connector --><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><!-- Test --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency>
</dependencies>
4.2 基础配置
4.2.1 数据源配置
在application.yml中配置数据源:
spring:datasource:url: jdbc:mysql://localhost:3306/mybatis_demo?useSSL=false&serverTimezone=UTC&characterEncoding=utf8username: rootpassword: passworddriver-class-name: com.mysql.cj.jdbc.Driverhikari:pool-name: HikariCPmaximum-pool-size: 20minimum-idle: 10idle-timeout: 30000max-lifetime: 60000connection-timeout: 30000
4.2.2 MyBatis 基本配置
mybatis:mapper-locations: classpath:mapper/*.xml # XML映射文件位置type-aliases-package: com.example.model # 实体类包名configuration:map-underscore-to-camel-case: true # 自动驼峰命名转换default-fetch-size: 100 # 默认获取数量default-statement-timeout: 30 # 超时时间(秒)
4.3 基础CRUD实现
4.3.1 实体类定义
@Data
@NoArgsConstructor
@AllArgsConstructor
public class User {private Long id;private String username;private String password;private String email;private Date createTime;private Date updateTime;
}
4.3.2 Mapper接口定义
@Mapper
public interface UserMapper {@Select("SELECT * FROM users WHERE id = #{id}")User findById(Long id);@Insert("INSERT INTO users(username, password, email, create_time, update_time) " +"VALUES(#{username}, #{password}, #{email}, now(), now())")@Options(useGeneratedKeys = true, keyProperty = "id")int insert(User user);@Update("UPDATE users SET username=#{username}, email=#{email}, update_time=now() WHERE id=#{id}")int update(User user);@Delete("DELETE FROM users WHERE id=#{id}")int delete(Long id);@Select("SELECT * FROM users")List<User> findAll();
}
4.3.3 Service层实现
@Service
@RequiredArgsConstructor
public class UserService {private final UserMapper userMapper;public User getUserById(Long id) {return userMapper.findById(id);}public List<User> getAllUsers() {return userMapper.findAll();}public int createUser(User user) {return userMapper.insert(user);}public int updateUser(User user) {return userMapper.update(user);}public int deleteUser(Long id) {return userMapper.delete(id);}
}
4.3.4 Controller层实现
@RestController
@RequestMapping("/api/users")
@RequiredArgsConstructor
public class UserController {private final UserService userService;@GetMapping("/{id}")public ResponseEntity<User> getUser(@PathVariable Long id) {User user = userService.getUserById(id);return ResponseEntity.ok(user);}@GetMappingpublic ResponseEntity<List<User>> getAllUsers() {List<User> users = userService.getAllUsers();return ResponseEntity.ok(users);}@PostMappingpublic ResponseEntity<Void> createUser(@RequestBody User user) {userService.createUser(user);return ResponseEntity.status(HttpStatus.CREATED).build();}@PutMapping("/{id}")public ResponseEntity<Void> updateUser(@PathVariable Long id, @RequestBody User user) {user.setId(id);userService.updateUser(user);return ResponseEntity.ok().build();}@DeleteMapping("/{id}")public ResponseEntity<Void> deleteUser(@PathVariable Long id) {userService.deleteUser(id);return ResponseEntity.noContent().build();}
}
4.4 XML映射方式实现
4.4.1 创建XML映射文件
在resources/mapper目录下创建UserMapper.xml:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd"><mapper namespace="com.example.mapper.UserMapper"><resultMap id="userResultMap" type="User"><id property="id" column="id"/><result property="username" column="username"/><result property="password" column="password"/><result property="email" column="email"/><result property="createTime" column="create_time"/><result property="updateTime" column="update_time"/></resultMap><select id="findById" resultMap="userResultMap">SELECT * FROM users WHERE id = #{id}</select><insert id="insert" parameterType="User" useGeneratedKeys="true" keyProperty="id">INSERT INTO users(username, password, email, create_time, update_time)VALUES(#{username}, #{password}, #{email}, now(), now())</insert><update id="update" parameterType="User">UPDATE users SET username=#{username}, email=#{email}, update_time=now()WHERE id=#{id}</update><delete id="delete">DELETE FROM users WHERE id=#{id}</delete><select id="findAll" resultMap="userResultMap">SELECT * FROM users</select>
</mapper>
4.4.2 修改Mapper接口
@Mapper
public interface UserMapper {User findById(Long id);int insert(User user);int update(User user);int delete(Long id);List<User> findAll();
}
4.5 分页查询实现
4.5.1 添加分页依赖
<dependency><groupId>com.github.pagehelper</groupId><artifactId>pagehelper-spring-boot-starter</artifactId><version>2.1.0</version>
</dependency>
4.5.2 配置分页插件
pagehelper:helper-dialect: mysqlreasonable: truesupport-methods-arguments: trueparams: count=countSql
4.5.3 实现分页查询
@Service
@RequiredArgsConstructor
public class UserService {private final UserMapper userMapper;public PageInfo<User> getUsersByPage(int pageNum, int pageSize) {PageHelper.startPage(pageNum, pageSize);List<User> users = userMapper.findAll();return new PageInfo<>(users);}
}@RestController
@RequestMapping("/api/users")
@RequiredArgsConstructor
public class UserController {private final UserService userService;@GetMapping("/page")public ResponseEntity<PageInfo<User>> getUsersByPage(@RequestParam(defaultValue = "1") int pageNum,@RequestParam(defaultValue = "10") int pageSize) {PageInfo<User> pageInfo = userService.getUsersByPage(pageNum, pageSize);return ResponseEntity.ok(pageInfo);}
}
5. MyBatis 高级特性
5.1 动态SQL高级用法
5.1.1 <choose>/<when>/<otherwise>示例
<select id