MyBatis從入門到精通:一站式學習指南
作為一款優秀的半自動ORM框架,MyBatis以其靈活的SQL控制和簡潔的配置方式,成為Java后端開發中持久層框架的首選。本文將從基礎概念到高級特性,全面講解MyBatis的使用方法,包含實用代碼示例和最佳實踐。
一、MyBatis核心概念
1. 什么是MyBatis?
MyBatis是一款半自動ORM(對象關系映射)框架,本質是對JDBC的封裝。與全自動ORM框架(如Hibernate)不同,MyBatis需要開發者手動編寫SQL語句,但免除了JDBC中繁瑣的連接管理、參數設置和結果集解析工作。
其核心優勢在于:
- 支持自定義SQL,便于復雜查詢和性能優化
- 強大的結果映射能力,自動完成數據庫記錄與Java對象的轉換
- 輕量靈活,易于集成Spring等主流框架
- 適用于高并發、大數據量的互聯網項目
2. 核心組件
MyBatis的工作流程依賴于以下核心組件:
- SqlSessionFactory:會話工廠,由SqlSessionFactoryBuilder根據配置文件創建,全局唯一
- SqlSession:數據庫會話對象,用于執行SQL操作,生命周期為方法級
- Mapper接口:定義數據庫操作方法的接口,無需實現類,MyBatis通過動態代理生成實現
- 映射文件:存儲SQL語句和映射規則,與Mapper接口對應
二、環境搭建(Maven)
1. 引入依賴
在pom.xml
中添加MyBatis核心依賴和數據庫驅動:
<dependencies><!-- MyBatis核心包 --><dependency><groupId>org.mybatis</groupId><artifactId>mybatis</artifactId><version>3.5.7</version></dependency><!-- MySQL驅動 --><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>8.0.26</version></dependency><!-- 單元測試 --><dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>4.12</version><scope>test</scope></dependency>
</dependencies>
2. 核心配置文件
創建mybatis-config.xml
(放在resources目錄下),配置數據庫連接和映射文件:
<?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="mysql"><environment id="mysql"><transactionManager type="JDBC"/><dataSource type="POOLED"><property name="driver" value="com.mysql.cj.jdbc.Driver"/><property name="url" value="jdbc:mysql://localhost:3306/mybatis_db?serverTimezone=UTC"/><property name="username" value="root"/><property name="password" value="root"/></dataSource></environment></environments><!-- 注冊映射文件 --><mappers><mapper resource="mapper/UserMapper.xml"/></mappers>
</configuration>
三、基本CRUD操作
1. 定義實體類
創建與數據庫表對應的POJO類:
public class User {private Integer id;private String username;private String sex;private String address;// 省略getter、setter和toString方法
}
2. Mapper接口與映射文件
(1)Mapper接口
public interface UserMapper {// 查詢所有用戶List<User> findAll();// 根據ID查詢User findById(Integer id);// 新增用戶void add(User user);// 更新用戶void update(User user);// 刪除用戶void delete(Integer id);
}
(2)映射文件(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="findAll" resultType="com.example.pojo.User">select * from user</select><!-- 根據ID查詢 --><select id="findById" parameterType="int" resultType="com.example.pojo.User">select * from user where id = #{id}</select><!-- 新增 --><insert id="add" parameterType="com.example.pojo.User">insert into user(username, sex, address) values(#{username}, #{sex}, #{address})</insert><!-- 更新 --><update id="update" parameterType="com.example.pojo.User">update user set username = #{username}, sex = #{sex}, address = #{address} where id = #{id}</update><!-- 刪除 --><delete id="delete" parameterType="int">delete from user where id = #{id}</delete>
</mapper>
3. 測試代碼
public class UserMapperTest {private SqlSession session;private UserMapper userMapper;@Beforepublic void init() throws IOException {// 讀取配置文件InputStream is = Resources.getResourceAsStream("mybatis-config.xml");// 創建SqlSessionFactorySqlSessionFactory factory = new SqlSessionFactoryBuilder().build(is);// 獲取SqlSessionsession = factory.openSession();// 獲取Mapper代理對象userMapper = session.getMapper(UserMapper.class);}@Testpublic void testFindAll() {List<User> users = userMapper.findAll();users.forEach(System.out::println);}@Testpublic void testAdd() {User user = new User();user.setUsername("張三");user.setSex("男");user.setAddress("北京");userMapper.add(user);session.commit(); // 手動提交事務}@Afterpublic void destroy() {session.close();}
}
注意:MyBatis的事務默認手動提交,執行增刪改操作后需調用
session.commit()
。
四、動態SQL
動態SQL是MyBatis的強大特性,可根據條件動態生成SQL片段,避免手動拼接SQL的繁瑣和錯誤。
1. <if>
標簽:條件判斷
<select id="findByCondition" parameterType="com.example.pojo.User" resultType="com.example.pojo.User">select * from user<where><if test="username != null and username != ''">and username like #{username}</if><if test="sex != null and sex != ''">and sex = #{sex}</if></where>
</select>
<where>
標簽會自動處理多余的AND
,替代傳統的where 1=1
寫法
2. <foreach>
標簽:遍歷集合
用于批量操作(如批量刪除):
<delete id="deleteBatch" parameterType="int">delete from user where id in<foreach collection="array" open="(" close=")" separator="," item="id">#{id}</foreach>
</delete>
collection
:集合類型(數組用array
,List用list
)item
:遍歷的元素名open/close
:SQL片段的開始/結束符separator
:元素間的分隔符
3. <choose>
標簽:多條件分支
類似Java的switch-case
:
<select id="findByLevel" parameterType="User" resultType="User">select * from user<where><choose><when test="level == 1">and age < 18</when><when test="level == 2">and age between 18 and 30</when><otherwise>and age > 30</otherwise></choose></where>
</select>
五、緩存機制
MyBatis提供兩級緩存,用于減少數據庫交互,提高查詢效率。
1. 一級緩存
- 作用域:SqlSession(會話級)
- 特性:默認開啟,同一SqlSession內的相同查詢會復用緩存
- 失效場景:執行增刪改操作、調用
clearCache()
或commit()
、關閉SqlSession
@Test
public void testL1Cache() {// 第一次查詢(從數據庫獲取)User user1 = userMapper.findById(1);// 第二次查詢(從一級緩存獲取)User user2 = userMapper.findById(1);System.out.println(user1 == user2); // true
}
2. 二級緩存
- 作用域:SqlSessionFactory(應用級)
- 特性:需手動開啟,同一工廠創建的SqlSession共享緩存
- 要求:緩存的POJO需實現
Serializable
接口
開啟步驟:
- 配置全局開關(mybatis-config.xml):
<settings><setting name="cacheEnabled" value="true"/>
</settings>
- 在映射文件中聲明緩存:
<mapper namespace="com.example.mapper.UserMapper"><cache size="1024"/> <!-- 開啟二級緩存 --><!-- SQL語句... -->
</mapper>
- 實體類實現序列化:
public class User implements Serializable {// 字段和方法...
}
六、關聯查詢
MyBatis支持一對一、一對多等關聯查詢,通過<association>
和<collection>
標簽實現。
1. 一對一查詢(如學生-班級)
<resultMap id="studentMap" type="com.example.pojo.Student"><id property="id" column="sid"/><result property="name" column="sname"/><!-- 關聯班級對象 --><association property="clazz" column="cid" javaType="com.example.pojo.Clazz"><id property="id" column="cid"/><result property="name" column="cname"/></association>
</resultMap><select id="findStudentWithClazz" resultMap="studentMap">select s.id sid, s.name sname, c.id cid, c.name cnamefrom student s left join clazz c on s.cid = c.id
</select>
2. 一對多查詢(如班級-學生)
<resultMap id="clazzMap" type="com.example.pojo.Clazz"><id property="id" column="cid"/><result property="name" column="cname"/><!-- 關聯學生集合 --><collection property="students" column="cid" ofType="com.example.pojo.Student"><id property="id" column="sid"/><result property="name" column="sname"/></collection>
</resultMap><select id="findClazzWithStudents" resultMap="clazzMap">select c.id cid, c.name cname, s.id sid, s.name snamefrom clazz c left join student s on c.id = s.cid
</select>
七、MyBatis Generator自動生成代碼
MyBatis Generator(MBG)是官方代碼生成器,可根據數據庫表自動生成POJO、Mapper接口和映射文件,減少重復工作。
1. 配置MBG插件(pom.xml)
<build><plugins><plugin><groupId>org.mybatis.generator</groupId><artifactId>mybatis-generator-maven-plugin</artifactId><version>1.3.7</version><configuration><configurationFile>src/main/resources/generatorConfig.xml</configurationFile><overwrite>true</overwrite></configuration></plugin></plugins>
</build>
2. 編寫配置文件(generatorConfig.xml)
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE generatorConfigurationPUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN""http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd">
<generatorConfiguration><!-- 數據庫驅動路徑 --><classPathEntry location="F:/maven/repository/mysql/mysql-connector-java/8.0.26/mysql-connector-java-8.0.26.jar"/><context id="mysql" targetRuntime="MyBatis3"><!-- 去除注釋 --><commentGenerator><property name="suppressAllComments" value="true"/></commentGenerator><!-- 數據庫連接 --><jdbcConnection driverClass="com.mysql.cj.jdbc.Driver"connectionURL="jdbc:mysql://localhost:3306/mybatis_db"userId="root"password="root"/><!-- 生成POJO --><javaModelGenerator targetPackage="com.example.pojo" targetProject="src/main/java"/><!-- 生成映射文件 --><sqlMapGenerator targetPackage="mapper" targetProject="src/main/resources"/><!-- 生成Mapper接口 --><javaClientGenerator type="XMLMAPPER"targetPackage="com.example.mapper"targetProject="src/main/java"/><!-- 指定表 --><table tableName="user"/></context>
</generatorConfiguration>
3. 運行生成命令
在Maven插件中執行mybatis-generator:generate
,自動生成以下文件:
User.java
:POJO類UserMapper.java
:Mapper接口UserMapper.xml
:映射文件UserExample.java
:復雜查詢條件構建類
八、分頁插件PageHelper
PageHelper是MyBatis常用的分頁插件,可簡化分頁查詢實現。
1. 引入依賴
<dependency><groupId>com.github.pagehelper</groupId><artifactId>pagehelper</artifactId><version>5.3.0</version>
</dependency>
2. 配置插件(mybatis-config.xml)
<plugins><plugin interceptor="com.github.pagehelper.PageInterceptor"><property name="helperDialect" value="mysql"/></plugin>
</plugins>
3. 使用示例
@Test
public void testPage() {// 設置分頁參數(頁碼從1開始,每頁3條)PageHelper.startPage(1, 3);// 執行查詢List<User> users = userMapper.findAll();// 封裝分頁結果PageInfo<User> pageInfo = new PageInfo<>(users);System.out.println("總條數:" + pageInfo.getTotal());System.out.println("總頁數:" + pageInfo.getPages());System.out.println("當前頁數據:" + pageInfo.getList());
}
總結
MyBatis以其靈活性和高效性,在Java持久層框架中占據重要地位。本文從環境搭建到高級特性,涵蓋了MyBatis的核心用法,包括CRUD操作、動態SQL、緩存機制、關聯查詢等。掌握這些內容后,可輕松應對日常開發中的數據庫操作需求。
建議在實際項目中根據場景選擇XML配置或注解開發(XML更適合復雜SQL,注解更簡潔),并合理使用緩存和分頁插件優化性能。