mybatis随心记1

85 阅读2分钟

我们熟悉的Mapper是mybatis帮我们实例化的接口(通过反射),前提是我们只使用了mybatis而没有与spring集成。如果我们将mybatis与spring进行集成,那么代理权就会到spring手里,并由ioc容器进行纳管。

因此,先不去管mybatis与spring集成的逻辑,会对任何一方的理解都产生干扰。

mybatis原生的开发逻辑是怎样的呢?

import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;

// 假设你有一个UserMapper接口
public interface UserMapper {
    User selectUserById(int id);
}

public class MybatisManualDemo {
    public static void main(String[] args) throws Exception {
        // 1. 加载mybatis配置文件
        String resource = "com/example/mybatis-config.xml";
        InputStream inputStream = Resources.getResourceAsStream(resource);

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

        try (SqlSession session = sqlSessionFactory.openSession()) { // 手动创建SqlSession
            // 3. 获取UserMapper接口的代理对象
            UserMapper userMapper = session.getMapper(UserMapper.class);

            // 4. 调用方法执行查询
            User user = userMapper.selectUserById(1);

            // 5. 处理结果
            System.out.println("Selected User: " + user.getName());

            // 6. 提交事务(如果需要)
            session.commit();
        } catch (Exception e) {
            // 如果出现异常,则回滚事务
            session.rollback();
            throw e;
        }
    }
}

在这个例子中,sqlSessionFactory.openSession() 是用来获取SqlSession实例的关键步骤,然后通过这个SqlSession实例来获取Mapper接口的代理对象,并执行数据库操作。在try-with-resources语句中,SqlSession会在finally块中自动关闭,确保资源正确释放。

我们目前只关注核心对象:SqlSession。这个类里面的方法你会看到功能比较清晰,就是我们熟悉的各种数据库操作。它的默认实现只有一个:DefaultSqlSession。其内部存在如下属性:

private final Executor executor;

DefaultSqlSession所有的实现逻辑都会交给Executor执行器实现。因此DefaultSqlSession只是一个门面,真正干活的是Executor

Executor主要有三个实现类和一个抽象类:其中BaseExecutor是一个抽象类,为一个模板类,提供了一级缓存的实现(会话级缓存)的实现,如果缓存中找不到,则会进入从数据库查找的逻辑,即

org.apache.ibatis.executor.BaseExecutor#query ——>
    org.apache.ibatis.executor.BaseExecutor#doQuery

doQuery方法在BaseExecutor中是一个抽象方法,交由Executor的三个实现类之一进行实现,分别是: SimpleExecutorReuseExecutorBatchExecutor

重点关注:

  1. 一级缓存的key是由什么决定的,关注BaseExecutor中的createCacheKey方法。该方法决定了哪些场景可以命中缓存
  2. 一级缓存什么时候会被清空,关注BaseExecutor中的clearLocalCache方法什么时候被调用
  3. 关注ReuseExecutor重用了什么。重用的其实是预编译的sql。
  4. 关注BatchExecutor批量更新的时候有什么特点(待完善)

而在Spring整合MyBatis后,通常会通过自动注入的方式得到SqlSessionTemplate或Mapper接口的代理对象,从而无需手动创建和关闭SqlSession。