• 欢迎访问搞代码网站,推荐使用最新版火狐浏览器和Chrome浏览器访问本网站!
  • 如果您觉得本站非常有看点,那么赶紧使用Ctrl+D 收藏搞代码吧

浅谈MyBatis 如何执行一条 SQL语句

mybatis 搞代码 4年前 (2022-01-09) 25次浏览 已收录 0个评论

前言

Mybatis 是 Java 开发中比较常用的 ORM 框架。在日常工作中,我们都是直接通过 Spring Boot 自动配置,并直接使用,但是却不知道 Mybatis 是如何执行一条 SQL 语句的,而这篇文章就是来揭开 Mybatis 的神秘面纱。

基础组件

我们要理解 Mybatis 的执行过程,就必须先了解 Mybatis 中都有哪一些重要的类,这些类的职责都是什么?

SqlSession

我们都很熟悉,它对外提供用户和数据库之间交互需要使用的方法,隐藏了底层的细节。它默认是实现类是 DefaultSqlSession

Executor

这个是执行器,SqlSession 中对数据库的操作都是委托给它。它有多个实现类,可以使用不同的功能。

Configuration

它是一个很重要的配置类,它包含了 Mybatis 的所有有用信息,包括 xml 配置,动态 sql 语句等等,我们到处都可以看到这个类的身影。

MapperProxy

这是一个很重要的代理类,它代理的就是 Mybatis 中映射 SQL 的接口。也就是我们本文来源gao@!dai!ma.com搞$$代^@码!网!常写的 Dao 接口。

工作流程

初步使用

首先,我们需要得到一个 SqlSessionFactory 对象,该对象的作用是可以获取 SqlSession  对象。

// 读取配置
InputStream resourceAsStream = Resources.getResourceAsStream("config.xml");
SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();
// 创建一个 SqlSessionFactory 对象
SqlSessionFactory sqlSessionFactory = sqlSessionFactoryBuilder.build(resourceAsStream);

当我们得到一个 SqlSessionFactory 对象之后,就可以通过它的 openSession 方法得到一个 SqlSession 对象。

 SqlSession sqlSession = sqlSessionFactory.openSession(true);

最后,我们通过 SqlSession 对象获取 Mapper ,从而可以从数据库获取数据。

// 获取 Mapper 对象
HeroMapper mapper = sqlSession.getMapper(HeroMapper.class);
// 执行方法,从数据库中获取数据
Hero hero = mapper.selectById(1);

详细流程

获取 MapperProxy 对象

我们现在主要关注的就是 getMapper 方法,该方法为我们创建一个代理对象,该代理对象为我们执行 SQL 语句提供了重要的支持。

// SqlSession 对象
@Override
public <T> T getMapper(Class<T> type) {
    return configuration.getMapper(type, this);
}

getMapper  方法里面委托 Configuration 对象去获取对应的 Mapper 代理对象,之前说过 Configuration 对象里面包含了 Mybatis 中所有重要的信息,其中就包括我们需要的 Mapper 代理对象,而这些信息都是在读取配置信息的时候完成的,也就是执行sqlSessionFactoryBuilder.build 方法。

// Configuration 对象
public <T> T getMapper(Class<T> type, SqlSession sqlSession) {
    return mapperRegistry.getMapper(type, sqlSession);
}

我们可以看到它又将获取 Mapper 代理对象的操作委托给了 MapperRegistry 对象(搁着俄罗斯套娃呢?),这个 MapperRegistry 对象里面就存放了我们想要的 Mapper 代理对象,如果你这么想,就错了,实际上,它存放的并不是我们想要的 Mapper 代理对象,而是 Mapper 代理对象的工厂,Mybatis 这里使用到了工厂模式。

public class MapperRegistry {

  private final Configuration config;
  private final Map<Class<?>, MapperProxyFactory<?>> knownMappers = new HashMap<>();

  public MapperRegistry(Configuration config) {
    this.config = config;
  }

  @SuppressWarnings("unchecked")
  public <T> T getMapper(Class<T> type, SqlSession sqlSession) {
    final MapperProxyFactory<T> mapperProxyFactory = (MapperProxyFactory<T>) knownMappers.get(type);
    if (mapperProxyFactory == null) {
      throw new BindingException("Type " + type + " is not known to the MapperRegistry.");
    }
    try {
      return mapperProxyFactory.newInstance(sqlSession);
    } catch (Exception e) {
      throw new BindingException("Error getting mapper instance. Cause: " + e, e);
    }
  }

  public <T> void addMapper(Class<T> type) {
    if (type.isInterface()) {
      if (hasMapper(type)) {
        throw new BindingException("Type " + type + " is already known to the MapperRegistry.");
      }
      boolean loadCompleted = false;
      try {
        knownMappers.put(type, new MapperProxyFactory<>(type));
        // It's important that the type is added before the parser is run
        // otherwise the binding may automatically be attempted by the
        // mapper parser. If the type is already known, it won't try.
        MapperAnnotationBuilder parser = new MapperAnnotationBuilder(config, type);
        parser.parse();
        loadCompleted = true;
      } finally {
        if (!loadCompleted) {
          knownMappers.remove(type);
        }
      }
    }
  }
}


搞代码网(gaodaima.com)提供的所有资源部分来自互联网,如果有侵犯您的版权或其他权益,请说明详细缘由并提供版权或权益证明然后发送到邮箱[email protected],我们会在看到邮件的第一时间内为您处理,或直接联系QQ:872152909。本网站采用BY-NC-SA协议进行授权
转载请注明原文链接:浅谈MyBatis 如何执行一条 SQL语句
喜欢 (0)
[搞代码]
分享 (0)
发表我的评论
取消评论

表情 贴图 加粗 删除线 居中 斜体 签到

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址