mybatis执行流程

一、什么是 MyBatis

MyBatis 是一个优秀的持久层框架,它通过 XML 或注解的方式将 SQL 映射到 Java 方法。MyBatis 提供了对 SQL 的灵活控制,避免了冗长的 JDBC 代码,使开发者可以专注于业务逻辑。


二、MyBatis 执行流程概述

MyBatis 的执行流程可以划分为以下几个步骤:

  1. 初始化:加载配置文件,创建 SqlSessionFactory
  2. 获取 SqlSession:从 SqlSessionFactory 获取 SqlSession,作为操作数据库的核心对象。
  3. 执行 SQL:调用映射文件中的方法(Mapper 方法)。
  4. 结果处理:将数据库查询结果映射到 Java 对象。
  5. 关闭资源:释放 SqlSession,避免资源泄露。

三、MyBatis 执行流程详细分析
1. 初始化阶段

初始化步骤

  1. 加载主配置文件(mybatis-config.xml)。
  2. 加载映射文件(Mapper.xml)。
  3. 构建 SqlSessionFactory
// 加载 MyBatis 配置文件
String resource = "mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);

// 创建 SqlSessionFactory
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);

关键点

  • 配置文件中定义了环境信息(如数据源)、插件等。
  • SqlSessionFactory 是 MyBatis 的核心对象,负责创建 SqlSession
2. 获取 SqlSession

获取 SqlSession

try (SqlSession sqlSession = sqlSessionFactory.openSession()) {
    // 使用 SqlSession 操作数据库
}

作用

  • SqlSession 是操作数据库的核心对象,封装了 JDBC 连接。
  • 提供了对数据库操作的基本方法,如 selectOneinsert 等。
3. Mapper 接口绑定

步骤

  1. 加载 Mapper.xml 中定义的 SQL 语句。
  2. 通过动态代理生成 Mapper 接口的实现类。

代码示例

UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
User user = userMapper.getUserById(1);

工作原理

  • Mapper 接口与 Mapper.xml 配置文件一一对应。
  • MyBatis 动态代理机制会拦截接口方法调用,将其映射到对应的 SQL 语句。
4. SQL 执行

SQL 执行分为以下步骤:

  1. 参数解析:解析方法传入的参数,替换到 SQL 中。
  2. SQL 执行:通过 JDBC 执行 SQL。
  3. 结果映射:将查询结果转换为 Java 对象。

代码示例

// 参数解析
Map<String, Object> params = new HashMap<>();
params.put("id", 1);

// 执行查询
User user = sqlSession.selectOne("com.example.mapper.UserMapper.getUserById", params);

底层调用

  • MyBatis 通过 PreparedStatement 执行 SQL。
  • 自动处理参数占位符(如 ?)并绑定实际参数。
5. 结果处理

MyBatis 提供了多种结果处理方式:

  1. 单行映射:将查询结果映射为 Java 对象。
  2. 多行映射:将查询结果映射为对象列表。
  3. 嵌套映射:处理复杂的关联关系。

代码示例

// 映射单行结果
User user = sqlSession.selectOne("com.example.mapper.UserMapper.getUserById", 1);

// 映射多行结果
List<User> users = sqlSession.selectList("com.example.mapper.UserMapper.getAllUsers");

工作原理

  • MyBatis 通过反射将数据库字段与 Java 属性匹配。
  • 如果字段名与属性名不同,可以通过 resultMap 显式定义映射关系。
6. 关闭资源

MyBatis 使用的是 手动事务管理,因此需要显式关闭资源:

代码示例

try (SqlSession sqlSession = sqlSessionFactory.openSession()) {
    // 操作数据库
    sqlSession.commit(); // 提交事务
} catch (Exception e) {
    sqlSession.rollback(); // 回滚事务
} finally {
    sqlSession.close(); // 释放资源
}

四、MyBatis 执行流程源码解析

1. SqlSessionFactoryBuilder
创建 SqlSessionFactory 的过程:

public SqlSessionFactory build(InputStream inputStream) {
    Configuration config = new XMLConfigBuilder(inputStream).parse();
    return new DefaultSqlSessionFactory(config);
}

XMLConfigBuilder 会解析 XML 配置文件并创建 Configuration 对象。

2. 动态代理生成 Mapper 实现

public <T> T getMapper(Class<T> type) {
    return mapperRegistry.getMapper(type, this);
}
  • MapperRegistry 使用 JDK 动态代理生成 Mapper 接口的实现类。

3. SQL 执行
SqlSessionselectOne 方法:

public <T> T selectOne(String statement, Object parameter) {
    List<T> list = this.selectList(statement, parameter);
    if (list.size() == 1) {
        return list.get(0);
    } else if (list.size() > 1) {
        throw new TooManyResultsException("Expected one result");
    }
    return null;
}

五、完整的 MyBatis 使用示例
1. 数据表结构
CREATE TABLE users (
    id INT PRIMARY KEY AUTO_INCREMENT,
    username VARCHAR(50),
    email VARCHAR(50)
);
2. Mapper 接口
public interface UserMapper {
    User getUserById(int id);
    List<User> getAllUsers();
    void insertUser(User user);
}
3. Mapper XML 文件

UserMapper.xml

<mapper namespace="com.example.mapper.UserMapper">
    <select id="getUserById" parameterType="int" resultType="com.example.model.User">
        SELECT * FROM users WHERE id = #{id}
    </select>

    <select id="getAllUsers" resultType="com.example.model.User">
        SELECT * FROM users
    </select>

    <insert id="insertUser" parameterType="com.example.model.User">
        INSERT INTO users (username, email) VALUES (#{username}, #{email})
    </insert>
</mapper>
4. 配置文件

mybatis-config.xml

<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/testdb"/>
                <property name="username" value="root"/>
                <property name="password" value="password"/>
            </dataSource>
        </environment>
    </environments>
    <mappers>
        <mapper resource="com/example/mapper/UserMapper.xml"/>
    </mappers>
</configuration>
5. 测试代码
public class MyBatisTest {
    public static void main(String[] args) throws IOException {
        // 加载 MyBatis 配置文件
        String resource = "mybatis-config.xml";
        InputStream inputStream = Resources.getResourceAsStream(resource);
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);

        try (SqlSession sqlSession = sqlSessionFactory.openSession()) {
            UserMapper userMapper = sqlSession.getMapper(UserMapper.class);

            // 插入数据
            User newUser = new User();
            newUser.setUsername("John");
            newUser.setEmail("john@example.com");
            userMapper.insertUser(newUser);

            // 查询数据
            User user = userMapper.getUserById(1);
            System.out.println("User: " + user);

            // 查询所有用户
            List<User> users = userMapper.getAllUsers();
            users.forEach(System.out::println);
        }
    }
}

六、总结

MyBatis 的执行流程围绕 SqlSession 展开,从配置初始化、Mapper 方法绑定到 SQL 执行和结果映射,每一步都有明确的职责和机制。MyBatis 提供了灵活的 SQL 控制,同时通过动态代理和映射机制简化了开发工作。

关键点总结

  1. 核心对象SqlSessionFactorySqlSession
  2. 动态代理:将 Mapper 接口绑定到 SQL。
  3. 执行过程:参数解析、SQL 执行、结果映射。
  4. 源码理解:掌握 MyBatis 的核心源码有助于更高效地解决问题。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Flying_Fish_Xuan

你的鼓励将是我创作最大的动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值