《Java EE SSM框架》学习笔记(7、MyBatis的解析和运行原理)

MyBatis的运行过程,分两步:

1、读取配置文件,缓存到Configuration对象,用以创建SqlSessionFactory。

2、SqlSession的执行过程。

掌握源码中的技巧、设计和开发模式,对我们大有裨益。

构建SqlSessionFactory过程:

MyBatis采用Builder模式,去创建SqlSessionFactory。

实际,通过SqlSessionFactoryBuilder去构建:

1、通过XMLConfigBuilder解析配置的XML文件,而后存入Configuration类对象。

ps:Configuration是个单例模式。

2、使用Configuration创建SqlSessionFactory。它是一个接口。

ps:MyBatis提供了默认的实现类DefaultSqlSessionFactory

 

上述就是所谓的Builder模式,对于复杂对象,使用一个类(Configuration)作为统领,一步一步地构建最终对象(SqlSessionFactory)。

源码分析:

1、从XMLConfigBuilder源码:配置的typeHandler会被注册到typeHandlerRegistry对象中去。

2、typeHandlerRegistry对象,存放在XMLConfigBuilder的父类BaseBuilder中去。

3、typeHandlerRegistry其实就是Configuration单例的一个属性。

4、因此,可通过Configuration单例,拿到typeHandlerRegistry对象,从而拿到typeHandler。

 

构建Configuration:

Configuration的作用:

1、读取基础和映射器XML;2、初始化MyBatis的别名等;3、提供单例,为后续SessionFactory服务;4、执行一些重要对象的初始化方法。

最重要的解析内容是,映射器。

 

构建映射器的内部组成:

当XMLConfigBuilder解析XML时,会将每一个SQL和其配置的内容保存起来。

一条SQL和它相关的配置信息,由3个部分组成的,分别为MappedStatement、SqlSource、BoundSql。

MappedStatement:是个类,包括了配置的SQL、SQL的id、resultMap等,还包括了sqlSource属性。

SqlSource:是提供BoundSql对象的地方。它是一个接口,有DynamicSqlSource等实现类。拥有唯一的接口方法,getBoundSqlSource();

BoundSql:是一个结果对象。通过它便可以拿到,要执行的SQL和参数。

映射器的内部组成

在插件中,往往需要拿到,BoundSql类,进而可以拿到当前运行的SQL和参数,从而对运行过程做出必要的修改。

BoundSql的3个主要属性:

parameterObject的功能:

1、传递简单对象,例如把int转化Integer来传递。

2、传递POJO或者Map;传递多个参数,没有@Param注解的话,ParameterObject将变为一个Map<String,Object>对象。因此,可通过#{1}、或者#{param1}。

3、有@Param注解,ParameterObject也将变为一个Map<String,Object>对象。只是把数字的键值置换为了@param注解的键值。

parameterMappings的功能:

它是个list,每个元素都是parameterMapping对象,该对象会描述参数,如名称、jdbcType、typeHandler等。通过它能实现参数与SQL的结合,以便PreparedStatement能够通过它,找到parameterObject对象的属性,设置参数。

sql属性的功能:

就是一条,被SqlSource解析后的SQL。

 

构建SqlSessionFactory:

真正的难点是,构建Configuration对象。

 

SqlSession运行过程:

sqlSession.getMapper的调用,运用了Configuration对象的getMapper方法。

Configuration又运用了,映射器的注册器Mapperregistry来获取对应的接口对象。

mapperRegistry.getMapper方法内:

首先判断是否注册了一个Mapper,若没有抛出异常,则启用工厂生成一个代理实例。

MapperProxyFactory类:

在newInstance方法中,可看到,动态代理对接口的绑定,它的作用就是生成动态代理对象(占位);

而代理的方法,则被放到了MapperProxy类中。

MapperProxy类源码:

若Mapper是一个JDK动态代理对象,在invoke方法内,执行execute方法,把SqlSession和当前运行的参数传递进去。

execute方法:

executeForMany方法:

通过源码可知:

它最后通过SqlSession对象去运行对象的SQL而已。MyBatis可以根据全路径和方法名,将接口和代理对象绑定起来。通过动态代理,让这个接口运行起来,而后采用命令模式,最后使用SqlSession接口的方法使得它能够执行对应的SQL。

 

SqlSession下的四大对象:

底层框架的四大对象:

Executor:代表执行器,StatementHandler:四大对象的核心,许多插件通过拦截它来实现。

ParameterHandler:处理SQL参数,ResultSetHandler:进行数据集的封装返回处理。

Executor:

SqlSession只是门面,真正干活的是,Executor。

有3种执行器,可在settings元素中配置:

SIMPLE(简易执行器)、REUSE(执行重用预处理语句)、BATCH(执行器重用语句和批量更新)

插件的原理:在调度真实的Executor方法之前,执行配置插件的代码。

在SimpleExecutor的doQuery方法中:

在prepareStatement方法中:

MyBatis根据Configuration来构建StatementHandler。用StatementHandler的prepare,进行预编译和基础设置,用parameterize来设置参数,用query时,将参数ResultHandler传递进去,使用它组织结果。

 

StatementHandler-数据库会话器:

创建的真实对象是一个RoutingStatementHandler对象,但不是真实的服务对象,它通过适配模式来找到对应的StatementHanlder来执行。

RoutingStatementHandler一共有3种:SimpleStatementHandler、PreparedStatementHandler、CallableStatementHandler;

RoutingStatementHandler源码中,定义了一个delegate的对象适配器,可根据配置来配适对应的StatementHandler对象。

Executor执行查询时,会执行,StatementHandler的prepare、parameterize和query方法。

在prepare方法中:

instantiateStatement方法,对SQL进行了预编译,然后做一些超时、获取最大行数等基础配置。

在parameterize方法中:

它是调用ParameterHandler来完成的。

在PreparedStatementHandler的query方法中:

在执行前参数和SQL都被prepare方法预编译,在parameterize方法中设置参数,只要执行SQL,就能返回结果了。

 

ParameterHandler-参数处理器:

ParameterHandler的实现类,DefaultParameterHandler,setParameters的实现:

可在parameterObject对象中取到参数,也选择使用typeHandler转换参数,typeHandler在MyBatis初始化时,注册在Configuration里。

 

ResultSetHanlder-结果处理器:

一般默认使用DefaultResultSetHandler的实现类。

 

SqlSession运行总结:

SqlSession通过Executor调度StatementHandler,后经过3步,prepared预编译SQL、parameterize设置参数、执行SQL。

parameterize可通过parameterHandler方法设置,参数根据typeHandler处理的。

执行SQL通过ResultSetHandler进行处理结果封装,update返回int,其它可通过typeHandler处理结果类型。

最后用ObjectFactory提供的规则,组装对象,返回给调用者。

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值