昨天,我研究了一下mybatis框架的内部构造,对他的配置文件,SqlSessionFactory,SalSession以及xxxMapper配置文件进行了分析。今天,我们再来对它的sql语句的执行过程分析一下。
昨天我们在解析xxxMapper文件的时候,这个文件的解析结果会被封装在MapperStatement这个类中,而这个类引用了Configuration这个类,然后数据被封装到这里边去,mybatis在执行sql语句是通过什么来执行的呢,我们现在已经了解了,Configuration存储配置文件的信息,MapperStatement存储xxxMapper文件中的sql语句,id等信息,SqlSessionFactory依赖于SqlSessionFactoryBuiler来构建默认的SqlSessionFactory,而SqlSession又依赖于SqlSessionFactory来构建,mybatis真是一环套一环。我们都知道,mybatis是一个持久层框架是用来操作数据库的,那么我们之前操作数据库用的是jdbc,jdbc执行sql语句用的是Statement这个类,mybatis想执行sql语句它肯定也要依赖这个类,那么它绝对也对jdbc进行了封装,而它封装起来的这个类就叫Executor。
以update方法为例来分析
这里我们以update方法为例来分析mybatis框架中sql语句的执行过程。
先看一张图,这是我们在最外层执行sql语句的起点。这里我们调用SqlSession接口中的insert方法执行sql的插入操作。
这里传入的第一个参数是我们的xxxMapper文件中的命名空间+sql语句的id。第二个参数就是要插入的数据。这个方法是在Sqlsession这个中的,我们直接去看他的实现类DefaultSqlSession。
我们看到,inser方法调用了自己类内部的update方法。我们的第一个参数叫statement,第二个参数叫parameter,我们再去看updat方法。
重点来了。我们观察这里传入的两个参数,update方法是如何来使用的,它将我们的statement传入了Configuration的getMapperedStatement方法。我上篇文章提到过,我们所有的配置信息都被mybatis解析并封装在Configuration中,所以这里的方法肯定就是根据我们传入的参数找到对应的配置信息,那我们传入的是命名空间+sql语句d,那么它的这个方法就是获取指定命名空间下的指定sql语句,最后赋值给了MapperStatement。接着我们就看到update方法返回调用了一个executor的update方法。我们注意方法参数中对我们的parameter参数进行了处理,具体怎么处理我们无需关注。我们先看executor,它就是Exexutor类型的。如下图,他是一个接口。然后有一个BaseExecutor的抽象类实现了这个接口,然后这个BaseExecutor有又四个子类,分别叫:BatchExecutor、CloseExecutor、ReuseExecutor、SimpleExecutor
我们直接去看他的实现类。这里以BatchExecutor为例。在BatchExecutor中有一个doUpdate方法。
这里,我们看到,他的传入参数依旧是MapperedStatement和Object的参数,我们不管他中间的一些对sql语句和参数的处理。我们只关注他们的去向。观察我红线框住的地方,首先判断了sql语句,接着创建了数据库连接,然后两个参数被传递到了SatementHandler这个对象。由这个对象创建了statement,最后调用了它内部的batch方法。batch需要传入一个statement。
它也是一个接口并且有一个抽象类实现。叫做:BaseStatementHandler,我们还是直接看它的实现类,以PrepareStatementHandler为例。
在这里,batch方法接收了一个Statement,然后又强转为了PreparedStatement,调用了其中的addBatch方法。是不是渐渐明了了,PreparedStatement我们在之前用jdbc的时候可以说是用到吐了。我们可以看一看它的实现类。
好了,mybatis的框架Executor的分析到此为止,水平有限,最后依旧放一张图,帮助大家理解mybatis。