1. Spring Boot与MyBatis整合概述
在现代Java企业级应用开发中,Spring Boot和MyBatis的组合已经成为主流技术栈之一。Spring Boot通过自动配置和约定优于配置的原则简化了Spring应用的初始搭建和开发过程,而MyBatis作为一款优秀的持久层框架,提供了灵活的SQL映射和对象关系映射能力。
这种组合特别适合需要精细控制SQL同时又希望享受Spring生态便利性的项目。与Hibernate等全自动ORM框架相比,MyBatis允许开发者直接编写和优化SQL语句,这在复杂查询和高性能要求的场景中尤为有价值。
2. 环境准备与项目初始化
2.1 创建Spring Boot项目
使用Spring Initializr(https://start.spring.io/)快速生成项目骨架,选择以下依赖:
- Spring Web (用于构建Web应用)
- MyBatis Framework (MyBatis集成)
- 对应数据库驱动 (如MySQL Driver)
或者通过命令行创建:
bash复制mvn archetype:generate -DgroupId=com.example -DartifactId=mybatis-demo -DarchetypeArtifactId=maven-archetype-quickstart -DinteractiveMode=false
2.2 添加必要依赖
在pom.xml中确保包含以下核心依赖:
xml复制<dependencies>
<!-- Spring Boot Starter -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- MyBatis Spring Boot Starter -->
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.2.0</version>
</dependency>
<!-- 数据库驱动 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
</dependencies>
2.3 配置数据源
在application.properties或application.yml中配置数据库连接:
properties复制# 数据库配置
spring.datasource.url=jdbc:mysql://localhost:3306/your_database?useSSL=false&serverTimezone=UTC
spring.datasource.username=root
spring.datasource.password=your_password
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
# MyBatis配置
mybatis.mapper-locations=classpath:mapper/*.xml
mybatis.type-aliases-package=com.example.model
3. MyBatis核心组件配置
3.1 实体类定义
创建与数据库表对应的Java实体类:
java复制package com.example.model;
public class User {
private Long id;
private String username;
private String email;
// 省略getter/setter和toString方法
}
3.2 Mapper接口开发
创建Mapper接口,使用注解或XML方式定义SQL操作:
java复制package com.example.mapper;
import com.example.model.User;
import org.apache.ibatis.annotations.*;
import java.util.List;
@Mapper
public interface UserMapper {
@Select("SELECT * FROM users WHERE id = #{id}")
User findById(Long id);
@Insert("INSERT INTO users(username, email) VALUES(#{username}, #{email})")
@Options(useGeneratedKeys = true, keyProperty = "id")
void insert(User user);
@Update("UPDATE users SET username=#{username}, email=#{email} WHERE id=#{id}")
void update(User user);
@Delete("DELETE FROM users WHERE id=#{id}")
void delete(Long id);
@Select("SELECT * FROM users")
List<User> findAll();
}
3.3 XML映射文件配置
对于复杂SQL,可以使用XML配置方式。在resources/mapper目录下创建UserMapper.xml:
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="com.example.model.User">
<id property="id" column="id" />
<result property="username" column="username"/>
<result property="email" column="email"/>
</resultMap>
<select id="findByUsername" resultMap="userResultMap">
SELECT * FROM users WHERE username LIKE CONCAT('%', #{username}, '%')
</select>
</mapper>
4. 业务层与服务集成
4.1 创建Service层
实现业务逻辑:
java复制package com.example.service;
import com.example.mapper.UserMapper;
import com.example.model.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.List;
@Service
public class UserService {
private final UserMapper userMapper;
@Autowired
public UserService(UserMapper userMapper) {
this.userMapper = userMapper;
}
@Transactional
public User createUser(User user) {
userMapper.insert(user);
return user;
}
public User getUserById(Long id) {
return userMapper.findById(id);
}
public List<User> getAllUsers() {
return userMapper.findAll();
}
// 其他业务方法...
}
4.2 控制器开发
创建REST API端点:
java复制package com.example.controller;
import com.example.model.User;
import com.example.service.UserService;
import org.springframework.web.bind.annotation.*;
import java.util.List;
@RestController
@RequestMapping("/api/users")
public class UserController {
private final UserService userService;
public UserController(UserService userService) {
this.userService = userService;
}
@GetMapping("/{id}")
public User getUser(@PathVariable Long id) {
return userService.getUserById(id);
}
@GetMapping
public List<User> getAllUsers() {
return userService.getAllUsers();
}
@PostMapping
public User createUser(@RequestBody User user) {
return userService.createUser(user);
}
}
5. 高级特性与优化
5.1 动态SQL
MyBatis提供了强大的动态SQL能力,可以在XML中使用if、choose、foreach等标签:
xml复制<select id="searchUsers" resultMap="userResultMap">
SELECT * FROM users
<where>
<if test="username != null">
AND username LIKE CONCAT('%', #{username}, '%')
</if>
<if test="email != null">
AND email LIKE CONCAT('%', #{email}, '%')
</if>
</where>
ORDER BY id
</select>
5.2 分页查询
集成PageHelper实现物理分页:
- 添加依赖:
xml复制<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper-spring-boot-starter</artifactId>
<version>1.4.1</version>
</dependency>
- 在Service中使用:
java复制public PageInfo<User> getUsersByPage(int pageNum, int pageSize) {
PageHelper.startPage(pageNum, pageSize);
List<User> users = userMapper.findAll();
return new PageInfo<>(users);
}
5.3 多数据源配置
对于需要连接多个数据库的场景:
- 配置多个数据源:
properties复制# 主数据源
spring.datasource.primary.url=jdbc:mysql://localhost:3306/db1
spring.datasource.primary.username=root
spring.datasource.primary.password=123456
spring.datasource.primary.driver-class-name=com.mysql.cj.jdbc.Driver
# 次数据源
spring.datasource.secondary.url=jdbc:mysql://localhost:3306/db2
spring.datasource.secondary.username=root
spring.datasource.secondary.password=123456
spring.datasource.secondary.driver-class-name=com.mysql.cj.jdbc.Driver
- 创建配置类:
java复制@Configuration
@MapperScan(basePackages = "com.example.mapper.primary", sqlSessionTemplateRef = "primarySqlSessionTemplate")
public class PrimaryDataSourceConfig {
@Bean(name = "primaryDataSource")
@ConfigurationProperties(prefix = "spring.datasource.primary")
public DataSource primaryDataSource() {
return DataSourceBuilder.create().build();
}
// 配置SqlSessionFactory和TransactionManager...
}
// 类似配置次数据源
6. 性能优化与最佳实践
6.1 SQL优化建议
- 为常用查询条件添加索引
- 避免SELECT *,只查询需要的字段
- 合理使用JOIN,避免过度连接
- 大数据量查询考虑分页
- 使用EXPLAIN分析SQL执行计划
6.2 MyBatis缓存配置
MyBatis提供两级缓存:
- 一级缓存:SqlSession级别,默认开启
- 二级缓存:Mapper级别,需要手动开启
开启二级缓存:
xml复制<mapper namespace="com.example.mapper.UserMapper">
<cache eviction="LRU" flushInterval="60000" size="512" readOnly="true"/>
<!-- 其他映射配置 -->
</mapper>
6.3 事务管理
Spring与MyBatis集成后,可以使用Spring的声明式事务管理:
java复制@Service
public class OrderService {
@Transactional(rollbackFor = Exception.class)
public void placeOrder(Order order) {
// 业务逻辑
}
}
7. 常见问题排查
7.1 映射问题排查
- 属性名与列名不匹配:使用@Results或resultMap明确指定映射关系
- 类型不匹配:确保Java类型与数据库类型兼容
- 嵌套结果映射:对于复杂对象,使用association和collection标签
7.2 性能问题排查
- 检查是否启用了二级缓存
- 分析SQL执行计划
- 检查是否使用了N+1查询问题
- 监控连接池使用情况
7.3 事务不生效问题
- 确保方法被Spring代理(在同一个类中调用事务方法不会生效)
- 检查异常类型是否被rollbackFor捕获
- 确认数据源TransactionManager配置正确
8. 测试与验证
8.1 单元测试
使用Spring Boot Test进行集成测试:
java复制@SpringBootTest
@Transactional
public class UserServiceTest {
@Autowired
private UserService userService;
@Test
public void testCreateUser() {
User user = new User();
user.setUsername("test");
user.setEmail("test@example.com");
User savedUser = userService.createUser(user);
assertNotNull(savedUser.getId());
}
}
8.2 API测试
使用TestRestTemplate测试Controller:
java复制@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
public class UserControllerTest {
@LocalServerPort
private int port;
@Autowired
private TestRestTemplate restTemplate;
@Test
public void testGetUser() {
User user = restTemplate.getForObject(
"http://localhost:" + port + "/api/users/1",
User.class);
assertNotNull(user);
}
}
9. 部署与监控
9.1 打包部署
使用Spring Boot Maven插件打包:
bash复制mvn clean package
java -jar target/mybatis-demo-0.0.1-SNAPSHOT.jar
9.2 Actuator监控
添加依赖启用监控端点:
xml复制<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
配置application.properties:
properties复制management.endpoints.web.exposure.include=health,info,metrics
management.endpoint.health.show-details=always
10. 项目结构建议
一个良好的Spring Boot + MyBatis项目结构示例:
code复制src/main/java
├── com.example
│ ├── config/ # 配置类
│ ├── controller/ # 控制器
│ ├── service/ # 服务层
│ ├── mapper/ # MyBatis Mapper接口
│ ├── model/ # 实体类
│ └── MybatisDemoApplication.java
src/main/resources
├── mapper/ # MyBatis XML映射文件
├── static/ # 静态资源
├── templates/ # 模板文件
├── application.properties
└── application-dev.properties
在实际开发中,根据项目复杂度可以进一步细分模块。对于大型项目,考虑按功能模块划分包结构,而不是按技术层次划分。
