📌 摘要
在 Java 后端開發中,MyBatis 是一個非常流行且靈活的持久層框架。它不像 Hibernate 那樣完全封裝 SQL,而是提供了對 SQL 的精細控制能力,同時又具備 ORM(對象關系映射)的功能。
本文將帶你從 MyBatis 基礎語法 到 高級特性 全面掌握這一持久層利器,內容涵蓋:
- MyBatis 簡介與核心優勢
- 快速入門示例(XML 和 注解方式)
- 映射文件詳解(resultMap、動態SQL等)
- 與 Spring / Spring Boot 整合實戰
- 性能優化技巧與最佳實踐
- 常見面試題解析
適合初學者入門和中高級開發者提升技能。
- 🔥 MyBatis中文網地址
🎯 一、為什么選擇 MyBatis?
? MyBatis 的特點:
特性 | 描述 |
---|---|
輕量級 | 無侵入性,無需繼承特定類或實現接口 |
SQL 控制強 | 手寫 SQL,便于性能調優 |
ORM 支持 | 自動將結果集映射為 Java 對象 |
動態 SQL | 提供 <if> 、<foreach> 等強大標簽 |
可擴展性強 | 支持自定義類型處理器、插件機制 |
與主流框架兼容 | 完美支持 Spring、Spring Boot |
? 適用場景:
- 對 SQL 有較高要求,需要定制化查詢
- 數據結構復雜、需頻繁優化性能
- 不希望被 Hibernate 的“黑盒”束縛
- 企業項目中已有大量 SQL 腳本遷移需求
🧱 二、MyBatis 核心組件介紹
組件 | 描述 |
---|---|
SqlSessionFactoryBuilder | 構建 SqlSessionFactory 工廠對象 |
SqlSessionFactory | 創建 SqlSession 實例的核心工廠 |
SqlSession | 執行 SQL 語句并獲取映射結果的主要接口 |
Mapper XML 文件 | 定義 SQL 語句和結果映射規則 |
Mapper 接口 | 通過接口綁定 XML 中的 SQL |
Configuration | 全局配置對象,包含數據源、事務管理器等信息 |
🚀 三、快速入門:搭建第一個 MyBatis 應用
? 開發環境準備:
- JDK 1.8+
- Maven 3.x
- MySQL 5.7+
- IDE(如 IntelliJ IDEA)
1. 添加依賴(Maven):
<!-- MyBatis -->
<dependency><groupId>org.mybatis</groupId><artifactId>mybatis</artifactId><version>3.5.10</version>
</dependency><!-- MySQL驅動 -->
<dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>8.0.29</version>
</dependency>
2. 配置 mybatis-config.xml
:
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configurationPUBLIC "-//mybatis.org//DTD Config 3.0//EN""http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration><environments default="development"><environment id="development"><transactionManager type="JDBC"/><dataSource type="POOLED"><property name="driver" value="com.mysql.cj.jdbc.Driver"/><property name="url" value="jdbc:mysql://localhost:3306/test_db?useSSL=false&serverTimezone=UTC"/><property name="username" value="root"/><property name="password" value="123456"/></dataSource></environment></environments><mappers><mapper resource="mapper/UserMapper.xml"/></mappers>
</configuration>
3. 編寫實體類 User.java
:
public class User {private Integer id;private String name;private String email;// Getter/Setter
}
4. Mapper 接口 UserMapper.java
:
public interface UserMapper {User selectById(Integer id);
}
5. Mapper XML 文件 UserMapper.xml
:
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.example.mapper.UserMapper"><select id="selectById" resultType="com.example.model.User">SELECT * FROM users WHERE id = #{id}</select>
</mapper>
6. 測試類 TestMyBatis.java
:
public class TestMyBatis {public static void main(String[] args) throws IOException {String resource = "mybatis-config.xml";InputStream inputStream = Resources.getResourceAsStream(resource);SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);try (SqlSession session = sqlSessionFactory.openSession()) {UserMapper mapper = session.getMapper(UserMapper.class);User user = mapper.selectById(1);System.out.println(user.getName());}}
}
🛠? 四、MyBatis 進階功能詳解
1. resultMap 結果映射
適用于字段名與屬性名不一致的情況:
<resultMap id="userResultMap" type="User"><id property="id" column="user_id"/><result property="name" column="user_name"/><result property="email" column="email"/>
</resultMap><select id="selectAllUsers" resultMap="userResultMap">SELECT user_id, user_name, email FROM users
</select>
2. 動態 SQL
<if>
條件判斷:
<select id="findUsers" parameterType="map" resultType="User">SELECT * FROM users<where><if test="name != null">AND name LIKE CONCAT('%', #{name}, '%')</if><if test="email != null">AND email = #{email}</if></where>
</select>
<choose>/<when>/<otherwise>
分支判斷:
<choose><when test="name != null">AND name = #{name}</when><when test="email != null">AND email = #{email}</when><otherwise>AND status = 1</otherwise>
</choose>
<foreach>
遍歷集合:
<delete id="deleteByIds">DELETE FROM users WHERE id IN<foreach collection="ids" item="id" open="(" separator="," close=")">#{id}</foreach>
</delete>
🔗 五、與 Spring / Spring Boot 整合實戰
1. Spring Boot + MyBatis 快速整合
添加依賴:
<dependency><groupId>org.mybatis.spring.boot</groupId><artifactId>mybatis-spring-boot-starter</artifactId><version>3.0.3</version>
</dependency>
application.yml 配置:
spring:datasource:url: jdbc:mysql://localhost:3306/test_db?useSSL=false&serverTimezone=UTCusername: rootpassword: 123456driver-class-name: com.mysql.cj.jdbc.Drivermybatis:mapper-locations: classpath:mapper/*.xmltype-aliases-package: com.example.model
Mapper 接口自動注入:
@Mapper
public interface UserMapper {@Select("SELECT * FROM users WHERE id = #{id}")User selectById(Integer id);
}
🚀 六、MyBatis 高級特性與優化技巧
? 使用 PageHelper 分頁插件:
<dependency><groupId>com.github.pagehelper</groupId><artifactId>pagehelper-spring-boot-starter</artifactId><version>1.4.2</version>
</dependency>
使用示例:
PageHelper.startPage(1, 10);
List<User> users = userMapper.selectAll();
PageInfo<User> pageInfo = new PageInfo<>(users);
? 自定義 TypeHandler 類型轉換器
public class BooleanTypeHandler implements TypeHandler<Boolean> {@Overridepublic void setNonNullParameter(PreparedStatement ps, int i, Boolean parameter, JdbcType jdbcType) {ps.setInt(i, parameter ? 1 : 0);}@Overridepublic Boolean getNullableResult(ResultSet rs, String columnName) throws SQLException {return rs.getInt(columnName) == 1;}
}
? 使用 MyBatis 插件(Interceptor)
可用于日志記錄、分頁、SQL 監控等。
@Intercepts({@Signature(type = StatementHandler.class, method = "prepare", args = {Connection.class, Integer.class})})
public class MyInterceptor implements Interceptor {@Overridepublic Object intercept(Invocation invocation) throws Throwable {// 前置處理邏輯System.out.println("Before executing SQL");// 執行原方法Object result = invocation.proceed();// 后置處理邏輯System.out.println("After executing SQL");return result;}@Overridepublic Object plugin(Object target) {return Plugin.wrap(target, this);}@Overridepublic void setProperties(Properties properties) {// 可以獲取配置的屬性}
}
💬 七、常見面試題解析
Q1: MyBatis 和 Hibernate 的區別?
答:Hibernate 是全自動 ORM 框架,屏蔽 SQL;MyBatis 是半自動 ORM,需手動編寫 SQL,更靈活可控。
Q2: #{} 和 ${} 的區別?
答:#{}
是預編譯占位符,防止 SQL 注入;${}
是字符串替換,存在注入風險。
Q3: 如何實現批量插入?
答:使用 <foreach>
標簽拼接多條 INSERT 語句,或結合 JDBC 的批處理。
Q4: 如何防止 N+1 查詢問題?
答:使用 <association>
或 <collection>
嵌套查詢,并啟用延遲加載(lazyLoadingEnabled)。
Q5: MyBatis 如何實現緩存?
答:一級緩存默認開啟(SqlSession級別),二級緩存需手動配置(Mapper級別)。
💡 八、總結
通過本文的學習,你應該已經掌握了:
- MyBatis 的基本原理與使用方式
- 如何使用 XML 或注解方式進行 CRUD 操作
- 動態 SQL 的編寫技巧
- resultMap 的使用與映射優化
- 與 Spring / Spring Boot 的整合方法
- 高級特性如分頁、插件、自定義類型處理器
- 常見面試題解析
MyBatis 是 Java 持久層開發中的利器,既能保持靈活性,又能兼顧開發效率,是構建高性能后端系統的首選之一。
- 如果你在學習過程中遇到任何疑問,歡迎在評論區留言交流!
- 👍 如果你覺得這篇文章對你有幫助,別忘了點贊、收藏、轉發哦!