MyBatis的解析和运行原理

来源:互联网 发布:迪沙药业集团如何 知乎 编辑:程序博客网 时间:2024/06/05 11:25

MyBatis的运行可分为两大部分,第一部分是读取配置文件缓存到Configuration对象,用来创建SqlSessionFactory,第二部分是SqlSession的执行过程。

先导入源码,不然你不知道方法之间是怎么调用。

一构建SqlSessionFactory过程

第一步,通过org.apache.ibatis.builder.xml.XMLConfigBuilder来解析配置的XML文件。我们一般是能过new SqlSessionFactoryBuilder().build()方法来创建SqlSessionFactory,最终于的是运行build(Reader reader, String environment, Properties properties)这个方法,接着创建一个XMLConfigBuilder对象来解析XML文件,把读到的数据存入到org.apache.ibatis.session.Configuration中 ,在把数据 存入到Configuration是调用过org.apache.ibatis.builder.xml.XMLConfigBuilderr的parseConfiguration(XNode root)方法,源码如下:

是不是知道为什么Mybatis的核心配置是有顺序的,不能打破它的顺序。

第二步,通过得到的configuration对象,调用qlSessionFactoryBuilder类中的build(Configuration config)方法,通过这个方法来调用DefaultSqlSessionFactory这类的构造方法

如果你想知道Mybatis所有的配置的信息,除了看API之外,还可以能Configuration的源码。


二SqlSession运行过程

在旧版本的MyBatis或者是iBatis中,使用的更多是SqlSession接口的方法进行操作,但是有新版的MyBatis建议使用Mapper。

我们一般通过SqlSession的getMapper方法来得到Mapper,面这个方法最终是通过org.apache.ibatis.binding.MapperProxyFactory这个类的newInstance方法产生,这个的重要代码如下

我们可以看到动态代理对接口的绑定,它的作用就是生成动态代理对象。面代理的方法则被放到了MapperProxy类中。我们还要看MapperProxy的源码。

看到invoke方法,一旦mapper是一个代理对象,那么它就会运行到invoke方法里面,显然mapper不是一个类,而是接口,所以它会生成MapperMethod对象,它是通过cachedMapperMethod方法对其初始化,然后执行execute方法,把sqlSession各当前运行的参数传递进去。我们查看这个方法的源码:

我主要看result = executeForMany(sqlSession, args);这名个方法,再查看这个方法的源码:

我们可以看到它最终还调用了SqlSession接口的方法,其它判断成立的条件,还是调用SqlSession接口的方法。

现在我们可以知道为什么MyBatis只用Mapper接口便能够运行SQL,因为映射器的XML文件的命名空间对应的便是这个接口的全路径,那么它根据全路径和方法但能够绑定起来,通过动态代理技术,让这个接口跑起来。

我们已经知道了映射器其实就是一个代理对象,进入MapperMethod的execute方法,通过简单判断就进入SqlSession接口提供的不同方法,但是不知道它们是怎么样运行的。Mapper执行的过程是通过Executor(代理执行器)、StatementHandler(使用JDBC的Statement和PrepareStatement进行操作)、ParameterHandler(用于SQL对参数的处理)、ResultHandler(对数据集ResultSet的封装返回处理)。

执行器(Executor),它是真正执行JAVA与数据库交互的东西,MyBatis提供了三种执行器,可心根据自己的需求在setting元素的defaultExecutorTope中配置,这里不介绍,因为与这篇博客关系不大,自己查API就可以了。我们打开SimpleExecutor这个类,随便打开找一个方法,这里为更好的体现方法的结构,这里贴的方法如下:

我们可以看到它是根据 Configuration来构建StatementHandler,然后使用prepareStatement方法对SQl编译 关对参数进行初始化,这个方法调用了StatementHandler的prepare()进行预编译和基础配置,然后通过StatementHandler的parameterize()来设置参数并执行。

数据库会话器(StatementHandler)就是专门处理数据库会话的,我们通过RoutingStatementHandler来得到StatementHandler对象,它也使用了代理设计模式,StatementHandler分为三种:CallableStatementHandler、SimpleStatementHandler和PreparedStatementHandler,在初始化的时候会根据上下文环境决定创建那个StatementHandler对象,我们以SimpleStatementHandler为例,我们 看下面的方法(在运行这个方法,还用调用instantiateStatement方法进行SQL预编译)

由于执行前参数和SQl都被prepare()方法预编译,参数在parameterixe()方法上已经进行了设置。

参数处理器(ParameterHandler)对预编译语句进行参数设置。实现类(DefaultParameterHandler)

结果处理器(ResultSetHandler),实现类(DefaultResultSetHandler),默认情况是通过这个类来处理。

SqlSession运行总结:SqlSession是通过Executo创建StatementHandler来运行的,面StatementHandler要经过下面三步:prepared预编译SQL;parameterize设置参数;query/执行SQl。


原创粉丝点击