Spring Boot 整合 MyBatis
Spring Boot 整合 MyBatis 是 Java 后端开发中非常经典的组合,能够快速实现数据访问层的开发。以下是详细的整合步骤和核心知识点:
一、环境准备
1. 依赖引入(Maven)
在 pom.xml
中添加核心依赖:
<!-- Spring Boot 父工程 -->
<parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.7.0</version> <!-- 版本可根据需求选择 -->
</parent><dependencies><!-- Spring Boot Web 依赖 --><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.2</version></dependency><!-- 数据库驱动(以 MySQL 为例) --><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><scope>runtime</scope></dependency><!-- 数据库连接池(HikariCP,Spring Boot 默认) --><dependency><groupId>com.zaxxer</groupId><artifactId>HikariCP</artifactId></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. 数据库配置
在 application.yml
(或 application.properties
)中配置数据库连接信息:
spring:datasource:driver-class-name: com.mysql.cj.jdbc.Driver # MySQL 8+ 驱动url: jdbc:mysql://localhost:3306/test_db?useUnicode=true&characterEncoding=utf8&serverTimezone=Asia/Shanghaiusername: rootpassword: 123456hikari:maximum-pool-size: 10 # 连接池最大连接数minimum-idle: 5 # 最小空闲连接数idle-timeout: 300000 # 空闲连接超时时间(毫秒)# MyBatis 配置
mybatis:mapper-locations: classpath:mapper/*.xml # Mapper XML 文件路径type-aliases-package: com.example.entity # 实体类包路径(简化 XML 中的类名)configuration:map-underscore-to-camel-case: true # 开启下划线转驼峰(如数据库字段 user_name → 实体类 userName)log-impl: org.apache.ibatis.logging.stdout.StdOutImpl # 打印 SQL 日志(开发环境用)
二、核心组件开发
1. 实体类(Entity)
对应数据库表结构,使用 Lombok 简化代码:
package com.example.entity;import lombok.Data;@Data // 自动生成 getter/setter/toString 等方法
public class User {private Long id;private String username; // 对应数据库 user_name 字段(下划线转驼峰生效)private Integer age;private String email;
}
2. Mapper 接口(数据访问层)
定义数据库操作方法,通过注解或 XML 编写 SQL:
package com.example.mapper;import com.example.entity.User;
import org.apache.ibatis.annotations.*;import java.util.List;@Mapper // 标记为 MyBatis Mapper 接口(或在启动类用 @MapperScan 批量扫描)
public interface UserMapper {// 1. 注解方式编写 SQL@Select("SELECT * FROM user WHERE id = #{id}")User getById(Long id);@Insert("INSERT INTO user(username, age, email) VALUES(#{username}, #{age}, #{email})")@Options(useGeneratedKeys = true, keyProperty = "id") // 自动返回自增主键int insert(User user);// 2. XML 方式编写 SQL(推荐复杂 SQL 使用)List<User> findAll(); // 对应 UserMapper.xml 中的 findAll 方法@Update("UPDATE user SET username = #{username}, age = #{age} WHERE id = #{id}")int update(User user);@Delete("DELETE FROM user WHERE id = #{id}")int delete(Long id);
}
3. Mapper XML 文件(可选)
复杂 SQL 建议写在 XML 中,路径对应 application.yml
中的 mapper-locations
:
创建 src/main/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"><!-- namespace 对应 Mapper 接口全路径 -->
<mapper namespace="com.example.mapper.UserMapper"><!-- 结果集映射(可选,字段名与实体类一致时可省略) --><resultMap id="BaseResultMap" type="User"><id column="id" property="id"/><result column="username" property="username"/><result column="age" property="age"/><result column="email" property="email"/></resultMap><!-- 对应 UserMapper 接口的 findAll 方法 --><select id="findAll" resultMap="BaseResultMap">SELECT * FROM user ORDER BY id DESC</select><!-- 复杂查询示例(条件查询) --><select id="findByCondition" parameterType="User" resultMap="BaseResultMap">SELECT * FROM user<where><if test="username != null and username != ''">AND username LIKE CONCAT('%', #{username}, '%')</if><if test="age != null">AND age = #{age}</if></where></select>
</mapper>
4. 服务层(Service)
封装业务逻辑,调用 Mapper 接口:
package com.example.service;import com.example.entity.User;
import com.example.mapper.UserMapper;
import org.springframework.stereotype.Service;import javax.annotation.Resource;
import java.util.List;@Service
public class UserService {@Resource // 注入 Mapper(或用 @Autowired)private UserMapper userMapper;public User getById(Long id) {return userMapper.getById(id);}public List<User> findAll() {return userMapper.findAll();}public int addUser(User user) {return userMapper.insert(user);}public int updateUser(User user) {return userMapper.update(user);}public int deleteUser(Long id) {return userMapper.delete(id);}
}
5. 控制层(Controller)
提供 API 接口,调用 Service 层:
package com.example.controller;import com.example.entity.User;
import com.example.service.UserService;
import org.springframework.web.bind.annotation.*;import javax.annotation.Resource;
import java.util.List;@RestController
@RequestMapping("/user")
public class UserController {@Resourceprivate UserService userService;@GetMapping("/{id}")public User getById(@PathVariable Long id) {return userService.getById(id);}@GetMapping("/all")public List<User> findAll() {return userService.findAll();}@PostMappingpublic int add(@RequestBody User user) {return userService.addUser(user);}@PutMappingpublic int update(@RequestBody User user) {return userService.updateUser(user);}@DeleteMapping("/{id}")public int delete(@PathVariable Long id) {return userService.deleteUser(id);}
}
6. 启动类
添加 @MapperScan
扫描 Mapper 接口(替代每个接口加 @Mapper
):
package com.example;import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;@SpringBootApplication
@MapperScan("com.example.mapper") // 扫描 Mapper 接口所在包
public class MyBatisApplication {public static void main(String[] args) {SpringApplication.run(MyBatisApplication.class, args);}
}
三、关键配置与优化
1. 批量操作
通过 XML 实现批量插入 / 更新:
<!-- 批量插入 -->
<insert id="batchInsert" parameterType="java.util.List">INSERT INTO user(username, age, email)VALUES<foreach collection="list" item="item" separator=",">(#{item.username}, #{item.age}, #{item.email})</foreach>
</insert>
2. 分页查询
集成 pagehelper
插件实现分页:
<!-- 添加依赖 -->
<dependency><groupId>com.github.pagehelper</groupId><artifactId>pagehelper-spring-boot-starter</artifactId><version>1.4.2</version>
</dependency>
使用方式:
// Service 层
public PageInfo<User> findByPage(int pageNum, int pageSize) {PageHelper.startPage(pageNum, pageSize); // 开启分页List<User> list = userMapper.findAll();return new PageInfo<>(list); // 封装分页结果
}
3. 事务管理
在 Service 层添加 @Transactional
注解开启事务:
@Service
public class UserService {@Transactional // 方法内的数据库操作具有事务性public void batchOperation() {userMapper.insert(new User("A", 20, "a@test.com"));int i = 1 / 0; // 模拟异常,事务会回滚userMapper.insert(new User("B", 21, "b@test.com"));}
}
四、常见问题与解决方案
Mapper 接口注入失败
- 确保
@Mapper
注解或@MapperScan
配置正确。 - 检查 Mapper 接口与 XML 文件的
namespace
是否一致。
- 确保
字段映射问题
- 开启
map-underscore-to-camel-case: true
解决下划线与驼峰命名冲突。 - 复杂映射使用
<resultMap>
手动指定。
- 开启
SQL 日志不打印
- 配置
mybatis.configuration.log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
。
- 配置
分页插件不生效
- 确保
PageHelper.startPage()
放在查询方法之前,且紧跟查询逻辑。
- 确保
五、总结
Spring Boot 整合 MyBatis 的核心步骤:
- 引入依赖(MyBatis Starter + 数据库驱动)。
- 配置数据库连接和 MyBatis 基础参数。
- 开发实体类、Mapper 接口(注解 / XML 写 SQL)、Service、Controller。
- 通过
@Mapper
或@MapperScan
注册 Mapper 接口。
这种整合方式兼顾了 MyBatis 的灵活性(SQL 可控)和 Spring Boot 的便捷性(自动配置),适合大多数企业级应用开发。