【MyBayis】MyBayis详解(2)MyBatis体系结构以及如何执行一条查询(SqlSessionFactory、SqlSession、Mapper)
一、SqlSessionFactory
简介:
- SqlSessionFactory是MyBatis的关键对象,通过SqlSessionFactoryBuilder对象类获得,而SqlSessionFactoryBuilder则可以从XML配置文件或一个预先定制的Configuration的实例构建出SqlSessionFactory的实例。
- 所有MyBatis的应用程序都以一个SqlSessionFactory对象的实例为核心。
- SqlSessionFactory是线程安全的,SqlSessionFactory一旦被创建应该在应用执行期间都存在。
- SqlSessionFactory不要重复创建多次,建议使用单例模式。
- SqlSessionFactory是创建SqlSession的工厂。
掌握以上概念后,我们从源码入手,了解整个SqlSessionFactory实现了什么共嫩,为什么是MyBatis的关键对象,如何加载一个Configuration对象以及如何创建一个SqlSession。
源码:
从源码可见,SqlSessionFactory接口里有不同参数重载的open方法,以及一个获取Configuration对象的方法,包含参数作用如下:
参数名 | 作用 |
---|---|
autoCommit | 是否自动提交(默认false) |
Connection | JDBC中与特定数据库的连接(会话),在连接上下文中执行sql语句并返回结果 |
Transaction Isolation Level | 事务隔离级别(参考:https://www.cnblogs.com/xrq730/p/5087378.html) |
ExecutorType | 执行器执行类型,有三种值,默认为simple(参考:https://blog.****.net/cleargreen/article/details/80614362) |
Configuration:
Configuration对象包含数据源、事务、mapper文件资源以及影响数据库行为属性设置settings。
通过xml文件生成Configuration对象时所用到的重要标签如下:
二、SqlSession
简介:
- SqlSession是MyBatis的关键对象,是执行持久化操作的独享,类似于JDBC中的Connection。
- 它是应用程序与持久层之间执行交互操作的一个对象,也是MyBatis执行持久化操作的关键对象。
- SqlSession对象完全包含以数据库为背景的所有执行SQL操作的方法,它的底层封装了JDBC连接,可以用SqlSession实例来直接执行被映射的SQL语句。
- 每个线程都应该有它自己的SqlSession实例。
- 使用完SqlSeesion之后关闭Session很重要,应该确保使用finally块来关闭它。
SqlSession四大对象:
- Execute:调度执行StatementHandler、ParmmeterHandler、ResultHandler执行相应的SQL语句;
- StatementHandler:使用数据库中Statement(PrepareStatement)执行操作,即底层是封装好了的prepareStatement;
- ParammeterHandler:处理SQL参数;
- ResultHandler:结果集ResultSet封装处理返回。
SqlSession如何执行一条查询?
从JDBC开始:
MyBatis本质上是封装了JDBC的一个ORM框架,那么它肯定也有对应的流程用来解析、处理一条SQL语句。
根据源码,以:Blog blog = (Blog) session.selectOne(“org.mybatis.example.BlogMapper.selectBlog”, 101);
为例。
那么得出对应关系:
三、Mapper接口
MyBatsi如何通过没有实现类的接口执行查询?
从代理模式说起:
我们从之前的通过SqlSession查询可以知道,执行一个查询需要给select提供:nameSpace、ID、param以及Return,那么一个Mapper接口是如何得到这些参数的呢?
最终方法会通过反射的方式调用MapperProxy中的invoke方法。
然后通过mapperMethod.execute(sqlSession, args);进行查询。
以mapperMethod的中的case select为例,方法最终返回结果还是调用了sqlSesion的select方法
那么代码是怎么一步一步走到MapperProxy中的invoke中的呢?
首先通过SqlSession.getMapper根据传入Mapper名称,调用Configuration中的mapperRegistry.getMapper,Configuration中维护了所有的mapper.xml解析出来的Mapper对象,然后调用MapperProxyFactory中的Proxy.newProxyInstance生成一个对应的代理实例,最终将数据转递到MapperProxy中的invoke进行查询。
四、总结
1、mybatis启动加载配置文件
- MyBatis在初始化的时候,会将MyBatis的配置信息全部加载到内存中,使用org.apache.ibatis.session.Configuration实例来维护。使用者可以使用sqlSession.getConfiguration()方法来获取。
-
此加载到内存中会生成一个对应的MappedStatement对象,然后会以key=”mapper接口路径”,value为MappedStatement对象的形式维护到Configuration的一个Map中。当以后需要使用的时候,只需要通过Id值来获取。
-
SqlSession的职能: SqlSession根据Statement ID, 在mybatis配置对象Configuration中获取到对应的MappedStatement对象,然后调用mybatis执行器来执行具体的操作。
2、开启一个数据库访问会话–创建sqlSession对象
MyBatis封装了对数据库的访问,把对数据库的会话和事务控制放到了SqlSession对象中。
3、利用sqlSession对象进行对话
以下使用一个selectList例子进行讲解:
4、MyBatis执行器Executor执行
-
根据参数MappedStatement 、param,动态地生成需要执行的SQL语句,用BoundSql对象表示创建缓存
-
根据参数,创建StatementHandler对象handler
-
创建Statement对象,把StatementHandler必要参数赋值给Statement对象,使用Statement对象进行查询
-
StatementHandler.query(Statement, ResultHandler)
-
处理返回结果,加工为想要的数据格式返回
Executor的功能和作用:
- 根据传递的参数,完成SQL语句的动态解析,生成BoundSql对象,供StatementHandler使用
- 为查询创建缓存,以提高性能
- 创建JDBC的Statement连接对象,进行操作
5、StatementHandler的作用
把必要参数赋值给Statement对象
处理结果集ResultSet,加工为想要返回的数据格式
6、MyBatis配置文件加载过程
- 调用SqlSessionFactoryBuilder对象的build(inputStream)方法;
- SqlSessionFactoryBuilder会根据输入流inputStream等信息创建XMLConfigBuilder对象;
- SqlSessionFactoryBuilder调用XMLConfigBuilder对象的parse()方法;
- XMLConfigBuilder对象返回Configuration对象;
- SqlSessionFactoryBuilder根据Configuration对象创建一个DefaultSessionFactory对象;
- SqlSessionFactoryBuilder返回 DefaultSessionFactory对象给Client,供Client使用。