MyBatis 是一个用于简化数据库操作的持久层框架,它的核心思想是 将 SQL 与 Java 代码解耦,让开发者专注于 SQL 的编写,同时自动处理重复的数据库操作步骤。
一、核心思想:SQL 与 Java 解耦
传统 JDBC 需要开发者手动管理数据库连接、拼接 SQL 参数、处理查询结果集,代码重复且容易出错。MyBatis 通过以下方式简化:
- 用 XML 或注解定义 SQL:将 SQL 语句写在配置文件中,与 Java 代码分离。
- 自动映射结果集:将数据库查询结果自动转为 Java 对象,无需手动解析。
二、核心组件与流程
1. 配置文件
- 全局配置文件(如
mybatis-config.xml
):配置数据库连接、事务管理、映射文件路径等。 - 映射文件(如
UserMapper.xml
):定义 SQL 语句(如<select>
,<insert>
)和结果映射规则。
2. 接口与映射绑定
- 定义一个 Java 接口(如
UserMapper
),接口方法与映射文件中的 SQL 一一绑定。 - 动态代理机制:MyBatis 自动为接口生成代理对象,调用接口方法时,实际执行对应的 SQL。
3. 执行流程
假设调用 userMapper.getUserById(1)
:
- 解析 SQL:找到
UserMapper.xml
中对应的 SQL,如<select id="getUserById" ...>
。 - 处理参数:将参数
1
自动设置到 SQL 中(如替换#{id}
)。 - 执行 SQL:通过
SqlSession
(类似数据库连接)发送 SQL 到数据库。 - 结果映射:将查询结果自动转为
User
对象(根据字段名与属性名的匹配,或自定义规则)。
三、关键机制
1. 动态 SQL
- 使用
<if>
,<foreach>
等标签,根据条件动态拼接 SQL。 - 示例:根据不同条件生成不同的查询语句。
2. 缓存机制
- 一级缓存:默认开启,同一个
SqlSession
内的查询结果会被缓存,提高性能。 - 二级缓存:跨
SqlSession
的缓存(需手动开启),减少数据库访问。
3. 执行器(Executor)
- 负责执行 SQL,并封装结果。MyBatis 提供了简单执行器、重用执行器、批量执行器等,适应不同场景。
四、对比 JDBC 的优势
- 代码简洁:无需手动管理连接、参数、结果集。
- 灵活性高:直接编写 SQL,适合复杂查询。
- 维护方便:SQL 集中管理,修改时无需改动 Java 代码。
五、通俗比喻
把 MyBatis 想象成一个 “智能翻译官”:
- 你告诉它:“我要查询 id=1 的用户”(调用
getUserById(1)
)。 - 它查字典(映射文件)找到对应的 SQL。
- 把参数
1
翻译成数据库能理解的语言,执行查询。 - 最后将数据库返回的“外语结果”翻译成 Java 对象,交还给你。
六、入门案例
1. 环境搭建
首先,你需要在项目中引入 MyBatis 相关依赖。如果使用 Maven 构建项目,在 pom.xml
文件中添加以下依赖:
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.7</version>
</dependency>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>2.0.6</version>
</dependency>
确保你的项目已经配置好数据库驱动依赖。
2. 配置文件
创建 MyBatis 的配置文件 mybatis-config.xml
,用于配置数据源、事务管理器等信息。
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
PUBLIC "-//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="${driver}"/>
<property name="url" value="${url}"/>
<property name="username" value="${username}"/>
<property name="password" value="${password}"/>
</dataSource>
</environment>
</environments>
<mappers>
<mapper resource="com/example/mapper/UserMapper.xml"/>
</mappers>
</configuration>
3. 创建实体类
创建与数据库表对应的 Java 实体类,例如 User
类:
public class User {
private Integer id;
private String name;
// Getters and Setters
}
4. Mapper 接口和 XML 映射文件
定义一个接口,比如 UserMapper
,并为其创建相应的 XML 映射文件。
UserMapper.java
public interface UserMapper {
User selectUser(int id);
}
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">
<select id="selectUser" parameterType="int" resultType="com.example.model.User">
SELECT * FROM users WHERE id = #{id}
</select>
</mapper>
5. 使用 SqlSessionFactory
在代码中初始化 SqlSessionFactory
并获取 SqlSession
来执行操作。
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.selectUser(1);
System.out.println(user.getName());
}
以上是 MyBatis 入门的一个基本流程,包括环境搭建、配置文件编写、实体类创建、Mapper 接口及映射文件的定义以及如何通过 SqlSession
执行数据库操作。
七、Mapper 接口及其对应的 XML 映射文件之间的映射
在 MyBatis 中,Mapper 接口及其对应的 XML 映射文件之间的映射是一个非常核心的概念,它允许开发者以面向接口的方式进行数据库操作。下面是关于 Mapper 接口和 XML 映射文件如何关联及映射的详细介绍:
-
命名空间(Namespace):XML 映射文件中的
namespace
属性必须与 Mapper 接口的全限定名完全一致。这是 MyBatis 用来将接口方法与 XML 文件中的 SQL 语句相匹配的关键。 -
SQL 语句 ID:在 Mapper 接口中定义的方法名应该与 XML 映射文件中
<select>
,<insert>
,<update>
,<delete>
标签的id
属性值相同。这样 MyBatis 就能知道哪个接口方法对应于哪条 SQL 语句。
映射过程
当你调用 Mapper 接口中的一个方法时,MyBatis 执行以下步骤来找到并执行相应的 SQL 语句:
- 解析 Mapper 接口:根据 Mapper 接口的全限定名找到对应的 XML 映射文件。
- 查找 SQL 语句:在找到的 XML 映射文件中,通过接口方法名作为
id
查找对应的 SQL 语句。 - 参数映射:如果接口方法有参数,则 MyBatis 会根据参数类型自动将 Java 对象转换为 JDBC 类型,并将其设置到 PreparedStatement 的参数中。
- 执行 SQL 语句:使用由 SqlSession 创建的 PreparedStatement 来执行查询或更新操作。
- 结果映射:从数据库获取的结果集将按照 XML 中指定的
resultType
或resultMap
转换回 Java 对象,并返回给调用者。
示例
假设有一个名为 UserMapper
的接口和一个对应的 XML 映射文件 UserMapper.xml
:
UserMapper.java
public interface UserMapper {
User selectUser(int id);
}
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">
<select id="selectUser" parameterType="int" resultType="com.example.model.User">
SELECT * FROM users WHERE id = #{id}
</select>
</mapper>
在这个例子中,UserMapper
接口的全限定名是 com.example.mapper.UserMapper
,这需要与 UserMapper.xml
文件中的 namespace
属性保持一致。同时,接口中的 selectUser
方法与 XML 文件中的 <select>
标签的 id
属性值相同,这意味着当调用 selectUser
方法时,MyBatis 会执行该 <select>
标签内的 SQL 语句。
这种机制使得 MyBatis 不仅易于使用,而且具有很强的灵活性和扩展性,非常适合用于构建数据驱动的应用程序。
八、各组件之间逻辑关系
1. 基本架构
MyBatis 主要由以下几个组件构成:
- SqlSessionFactory:这是 MyBatis 的入口点。通过 SqlSessionFactoryBuilder 根据配置文件或配置类创建 SqlSessionFactory 实例。
- SqlSession:代表一个与数据库执行 SQL 操作的会话。可以通过 SqlSessionFactory 获取 SqlSession 对象。
- Mapper 接口和 XML 映射文件:Mapper 接口定义了对数据库操作的方法签名,而 XML 映射文件则提供了具体的 SQL 语句以及结果映射规则。
2. 工作流程
配置阶段
- 读取配置:MyBatis 从
mybatis-config.xml
文件(或其他形式的配置)中读取全局配置信息,包括数据源、事务管理器等。 - 加载映射文件:同时也会加载 Mapper 接口及其对应的 XML 映射文件,解析其中的 SQL 语句、参数映射、结果映射等内容。
运行阶段
- 创建 SqlSessionFactory:基于配置信息,通过 SqlSessionFactoryBuilder 创建 SqlSessionFactory 实例。
- 获取 SqlSession:通过 SqlSessionFactory 开启 SqlSession,它是 MyBatis 与数据库交互的核心对象。
- 执行 SQL 语句:通过 SqlSession 获得 Mapper 接口的代理对象,调用其方法执行相应的 SQL 语句。
- 处理结果集:SQL 执行后,MyBatis 会根据映射文件中的配置将结果集自动映射到 Java 对象中,并返回给调用者。
- 提交或回滚事务:根据业务逻辑决定是否提交或回滚当前事务。
- 关闭 SqlSession:在操作完成后,必须关闭 SqlSession 以释放资源。
3. 核心机制
- 动态 SQL:MyBatis 支持动态生成 SQL 语句,可以根据不同的条件组合 SQL 片段,提高代码的灵活性和复用性。
- 缓存机制:为了提高性能,MyBatis 提供了一级缓存(SqlSession 级别)和二级缓存(跨 SqlSession 共享),减少数据库访问次数。
- 插件机制:MyBatis 允许通过插件扩展功能,比如分页、日志记录等。插件可以拦截四大对象(Executor、StatementHandler、ParameterHandler、ResultSetHandler)的行为。
通过上述过程,MyBatis 将复杂的 JDBC 操作封装起来,提供更加简洁易用的 API 给开发者,同时也保留了足够的灵活性和控制力,使得开发者可以根据需要定制化 SQL 和结果映射逻辑。