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,注解更简洁),并合理使用缓存和分页插件优化性能。