
Mybatis是什么
市面上常用的ORM持久层框架,底层是封装了JDBC
什么是ORM
ORM:Object Relational Mapper/对象关系映射
实现面向对象编程语言里不同类型系统的数据之间的转换。(可以理解为Java是中文,SQL是英语,ORM就是中间的翻译)
ORM框架
MyBatis, Hibernate ......(这两个是国内常用的ORM框架)
MyBatis和Hibernate的对比
MyBatis与JDBC的区别
MyBatis实现
MyBatis核心组件
| 组件名 | 作用 |
|---|---|
| SqlSession | 作为MyBatis工作的主要顶层API,和数据库交互的会话,完成数据库增删改查功能 |
| Executor | MyBatis执行器,是MyBatis 调度的核心,负责SQL语句的生成和查询缓存的维护 |
| StatementHandler | 封装了JDBC Statement操作,负责对JDBC statement 的操作,如设置参数、将Statement结果集转换成List集合。 |
| ParameterHandler | 负责对用户传递的参数转换成JDBC Statement 所需要的参数 |
| ResultSetHandler | 负责将JDBC返回的ResultSet结果集对象转换成List类型的集合 |
| TypeHandler | 负责java数据类型和jdbc数据类型之间的映射和转换 |
| MappedStatement | 该类维护了Mapper配置文件中的一条SQL语句节点,<select>,<insert>等等 |
| SqlSource | 负责根据用户传递的parameterObject,动态地生成SQL语句,将信息封装到BoundSql对象中,并返回 |
| BoundSql | 表示动态生成的SQL语句以及相应的参数信息 |
| Configuration | MyBatis所有的配置信息都维持在Configuration对象之中 |
记住上面这些关键字,面试中问到MyBatis一定用的上!划重点!!
代码案例
public static void main(String[] args) throws IOException {
String resource = "mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
try (SqlSession session = sqlSessionFactory.openSession()){
User user = session.selectOne("com.sunfounder.testapp.UserMapper.getUser",1);
System.out.println("User:"+user);
}
}
我们将会通过上面的代码,了解MyBatis的初始化工作,以及MyBatis是如何执行一条查询语句的
获取数据配置源,创建SqlSession工厂
概述
SqlSessions 是由 SqlSessionFactory 实例创建的。SqlSessionFactory 对象包含创建 SqlSession 实例的所有方法。而 SqlSessionFactory 本身是由 SqlSessionFactoryBuilder 创建的,它可以从 XML、注解或手动配置 Java 代码来创建
底层实现调用链
org.apache.ibatis.session.SqlSessionFactoryBuilder.build(java.io.InputStream)
>org.apache.ibatis.session.SqlSessionFactoryBuilder.build(java.io.InputStream, java.lang.String, java.util.Properties)
// 加载xml文件 将对应值放入Configration中,并返回
> public Configuration org.apache.ibatis.builder.xml.XMLConfigBuilder.parse()
// 读取XML配置文件的标签,并填充到Configuration类中
>org.apache.ibatis.builder.xml.XMLConfigBuilder.parseConfiguration(XNode root)
// 加载environment节点
> org.apache.ibatis.builder.xml.XMLConfigBuilder.environmentsElement(XNode context)
// 加载Datasource节点 配置数据库工厂
> org.apache.ibatis.builder.xml.XMLConfigBuilder.dataSourceElement(XNode context)
// 获取对应的MySQL连接用户信息(root账户账户密码等)
> org.apache.ibatis.parsing.XNode.getChildrenAsProperties()
> org.apache.ibatis.builder.BaseBuilder.resolveClass(String alias)
> org.apache.ibatis.builder.BaseBuilder.resolveAlias
// 注册类型
> org.apache.ibatis.type.TypeAliasRegistry.resolveAlias
// 通过工厂(DataSourceFactory)获取数据库源DataSource
> org.apache.ibatis.datasource.DataSourceFactory.getDataSource
// 配置/设置Configuration对象对应的全局变量Environment参数
> org.apache.ibatis.session.Configuration.setEnvironment(Environment environment)
> org.apache.ibatis.mapping.Environment.Builder.build
// 读取Configuration类,创建SqlSessionFactory
> org.apache.ibatis.session.SqlSessionFactoryBuilder#build(org.apache.ibatis.session.Configuration)
- 开发者调用SqlSessionFactoryBuilder 的 build() 并传入全局配置文件
- 在创建SqlSessionFactory之前调用XMLConfigBuilder的parse方法,该方法返回已经通过读取全局配置文件配置好的 Configuration 实例(具体读取的处理在 parseConfiguration() 中实现)
- 调用SqlSessionFactoryBuilder中需要Configuration类参数的 build() 创建 SqlSessionFactory
图解
获取SqlSession实例
底层实现调用链
// SqlSessionFactory获取SqlSession实例方法
org.apache.ibatis.session.SqlSessionFactory.openSession()
>org.apache.ibatis.session.defaults.DefaultSqlSessionFactory.openSession()
// 该方法返回 DefaultSqlSession
>SqlSession org.apache.ibatis.session.defaults.DefaultSqlSessionFactory.openSessionFromDataSource(ExecutorType execType, TransactionIsolationLevel level, boolean autoCommit)
// 获取全局配置参数
> org.apache.ibatis.session.Configuration.getEnvironment()
// 创建执行器(默认是SIMPLE), 返回 SimpleExecutor , 一共有三种执行器
> org.apache.ibatis.session.Configuration.newExecutor(org.apache.ibatis.transaction.Transaction, org.apache.ibatis.session.ExecutorType)
// 实例化
> org.apache.ibatis.executor.SimpleExecutor
// 有参构造函数创建 DefaultSqlSession对象,openSession方法要返回的就是这个对象
> org.apache.ibatis.session.defaults.DefaultSqlSession()
- 开发者调用openSession() 创建SqlSession会话
- 方法内部调用 DefaultSqlSessionFactory 的openSessionFromDataSource()
- 通过读取 Configuration 初始化 Executor/执行器 ,并返回DefaultSqlSessionFactory对象。应用程序中,SqlSession的初始化一般只执行一次
图解
selectOne()语句的实现
实现调用链
// 入口,顶层API
> 1.org.apache.ibatis.session.SqlSession.selectOne(java.lang.String, java.lang.Object)
// selectone的本质其实就是selectList后处理,返回数组中的第一个
> 2.org.apache.ibatis.session.defaults.DefaultSqlSession.selectList(java.lang.String, java.lang.Object)
// 跳转到该重载方法
> 3.org.apache.ibatis.session.defaults.DefaultSqlSession.selectList(java.lang.String, java.lang.Object, org.apache.ibatis.session.RowBounds)
// 得到SQL语句维护对象
> 4.org.apache.ibatis.session.Configuration.getMappedStatement(java.lang.String)
// 通过传入的 StatementId找到对应的MapperStatement对象
> 5.java.util.Map.get()
// 执行查询
> 6.org.apache.ibatis.executor.Executor.query(org.apache.ibatis.mapping.MappedStatement, java.lang.Object, org.apache.ibatis.session.RowBounds, org.apache.ibatis.session.ResultHandler()
// 为当前的查询创建一个缓存Key
> 7.org.apache.ibatis.executor.BaseExecutor.createCacheKey
/* 判断是否走缓存还是从DB中查询 */
> 8.org.apache.ibatis.executor.BaseExecutor.query(此处省略过长的形参)
// 判断list是否为空,不为空则从缓存中查找
// 走数据库查询
> 9.org.apache.ibatis.executor.BaseExecutor.queryFromDatabase
// 执行查询,返回List 结果,将查询的结果放入缓存之中
> 10.org.apache.ibatis.executor.BaseExecutor.doQuery()
// 创建StatementHandler对象来执行查询操作
> 11.org.apache.ibatis.session.Configuration.newStatementHandler()
// 创建java.Sql.Statement对象,该类属于JDBC接口,能够发送 SQL 命令或 PL/SQL 命令到数据库,并从你的数据库接收数据。
> 12.org.apache.ibatis.executor.BaseExecutor.prepareStatement()
// 调用StatementHandler.query()方法
// 内部实现是封装了JDBC查询方法返回List结果集
> 13.org.apache.ibatis.executor.statement.StatementHandler.query(Statement statement, ResultHandler resultHandler)
// 返回结果集
> 14.org.apache.ibatis.executor.resultset.ResultSetHandler.handleResultSets()
- 开发者通过SqlSession对象调用顶层API:selectOne()
- 顶层方法的内部其实是调用selectList,内部进行了处理返回结果集的第一个
- 获取MapperStatement对象,该对象保存在Map中,通过StatementId查找到MapperStatement,该对象保存一条SQL语句的相关信息
- 调用执行器的query方法
- 创建对应的缓存Key,但并没放入缓存中
- 调用执行器中的重载query方法,多了缓存key参数
- 该方法会判断是从缓存中获取结果集还是去数据库中查找数据(我们假设没有缓存),那么会执行 queryFromDatabase()
- 内部会调用SimpleExecute(默认创建的执行器)的doQuery方法
- 内部创建一个StatementHandler对象,然后将必要的参数传递给 StatementHandler,使用StatementHandler的 query() 来完成对数据库的查询(底层通过statement类实现查询),最终返回List结果集。
图解
解释下,如果使用<>会出现Bug,使用《》代替,谅解