目錄
- 引言
- 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