前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >数据库技术知识点总结之二——Mybatis

数据库技术知识点总结之二——Mybatis

作者头像
剑影啸清寒
发布2020-07-13 10:27:39
2800
发布2020-07-13 10:27:39
举报
文章被收录于专栏:琦小虾的Binary琦小虾的Binary

接上篇《数据库技术知识点总结之一——事务隔离级别》

二. Mybatis

2.1 MyBatis 是如何执行的?

参考网址:《深入浅出Mybatis系列(十)—SQL执行流程分析(源码篇)》 MyBatis 执行一次指令的过程有两个阶段,获取 Mapper执行语句

2.1.1 获取 Mapper

**SqlSession 是 MyBatis 的灵魂。**获取 Mapper 的操作也是在 SqlSession 接口中执行的。但首先应该考虑的是 SqlSession 如何创建。

2.1.2 SqlSession 的构建

首先,SqlSessionFactoryBuilder 用来构建 SqlSessionFactory。

通常由于我们使用的是 Spring 与 Mybatis 共同使用,所以使用到了 org.apache.ibatis.spring 中的 SqlSessionFactoryBean。在该类中指定一个 xml 文件,同时 SqlSessionFactoryBean 中有一个 SqlSessionFactoryBuilder。将 XML 文件传入 builder,即可构建 SqlSessionFactory。

SqlSessionFactory 全局基本上只有一个(如果有多个,说明系统设计是有问题的),通过 SqlSessionFactory 构建 SqlSession。SqlSessionFactory 最重要的方法就是 openSession() 方法。通过 openSession() 方法一系列的调用,最终会创建一个包装了 Statement 的 executor,以及一个 DefaultSqlSession。

每一个线程都有一个 SqlSession,用于执行 Sql 的增删改查、事务、获取 Mapper 接口等基本操作。

2.1.3 获取 Mapper

获取 Mapper 接口也是 SqlSession 的主要功能。Mapper.getMapper() 方法执行过程中,经过多次调用,在 MapperProxyFactory 中通过代理方式 newInstance() 真正的获取 Mapper 方法。

代码语言:javascript
复制
  @SuppressWarnings("unchecked")
  protected T newInstance(MapperProxy<T> mapperProxy) {
    //动态代理我们写的dao接口
    return (T) Proxy.newProxyInstance(mapperInterface.getClassLoader(), new Class[] { mapperInterface }, mapperProxy);
  }
  
  public T newInstance(SqlSession sqlSession) {
    final MapperProxy<T> mapperProxy = new MapperProxy<T>(sqlSession, mapperInterface, methodCache);
    return newInstance(mapperProxy);
  }

2.2 执行语句

获取了 Mapper 之后就可以执行语句了。

2.2.1 MapperProxy

获取的 Mapper 接口并不完全是接口本身,而是被 MapperProxy 类代理的接口。MapperProxy 是实现了动态代理接口 InvocactionHandler 的实现类,所以执行这里的 query 语句也是通过代理类通过反射调用执行的。

代码语言:javascript
复制
  @Override
  public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
    if (Object.class.equals(method.getDeclaringClass())) {
      try {
        return method.invoke(this, args);
      } catch (Throwable t) {
        throw ExceptionUtil.unwrapThrowable(t);
      }
    }
    final MapperMethod mapperMethod = cachedMapperMethod(method);
    //主要交给MapperMethod自己去管
    return mapperMethod.execute(sqlSession, args);
  }

2.2.2 Executor

在 MapperMethod 的 execute 方法中进行判断,准备真正执行语句,执行过程还是会交给 SqlSession。比如执行 selectList 方法,selectList 方法会在前面 SqlSessionFactory 中构建的 executor 中调用 query 方法,然后再经过层层调用,到达 doQuery 方法。doQuery 方法中获取到了 StatementHandler,执行 query 方法:

代码语言:javascript
复制
public <E> List<E> doQuery(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) throws SQLException {
    Statement stmt = null;
    try {
      Configuration configuration = ms.getConfiguration();
      StatementHandler handler = configuration.newStatementHandler(wrapper, ms, parameter, rowBounds, resultHandler, boundSql);
      stmt = prepareStatement(handler, ms.getStatementLog());
      //StatementHandler封装了Statement, 让 StatementHandler 去处理
      return handler.<E>query(stmt, resultHandler);
    } finally {
      closeStatement(stmt);
    }
  }

在 StatementHandler 中执行的 query 如下:

代码语言:javascript
复制
  public <E> List<E> query(Statement statement, ResultHandler resultHandler) throws SQLException {
     // 到此,原形毕露, PreparedStatement, 这个大家都已经滚瓜烂熟了吧
    PreparedStatement ps = (PreparedStatement) statement;
    ps.execute();
    // 结果交给了ResultSetHandler 去处理
    return resultSetHandler.<E> handleResultSets(ps);
  }

最后到了 PreparedStatement 的执行,就到了 JDBC 真正执行的地方。至此一次 SQL 执行流程完毕。

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2020-07-09 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 二. Mybatis
    • 2.1 MyBatis 是如何执行的?
      • 2.1.1 获取 Mapper
      • 2.1.2 SqlSession 的构建
      • 2.1.3 获取 Mapper
    • 2.2 执行语句
      • 2.2.1 MapperProxy
      • 2.2.2 Executor
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档