通过 Mybaits 动态代理,我们了解到Mybaits将接口调用通过反射映射到SqlSession中对应的方法。
那么SqlSession是如果对相关的操作进行处理呢?
跟进Mybaits源码,可以看到SqlSession的一次query执行时序图如下:

其中核心成员包括:
- SqlSessionFactory:SqlSession工厂类,用于生成对应的SqlSession。
- SqlSession: 对数据库进行相关操作,实现类中包括Configuration 和 Executor。
- Executor:Executor通过对MappedStatement、parameter等参数生成对应的StatemenHandler,调用StatemenHandler的方法。
- StatementHandler:Statement包装类,通过JDBC与数据库进行通信。
- ResultSetHandler:对StatemHandler方法调用返回的元数据进行处理,生成result对象。
接下来通过跟踪Mybatis源码中的一个test看下具体实现:
-
首先,获取SqlSessionFactory:

-
通过SqlMapper获取SqlSession:

进入上图2 方法:

看到调用了selectList方法,如果返回多个值则报异常,否则取出第一个值,接下来进如selectList()

SqlSession对接口反射过来的参数进行处理,根据xml中定义方法,调用Executror相关的方法,相当于做了分层 ,SqlSession和MapMethod来确定用户的操作类型,而有Executor来做具体的执行, -
接下来跟进Executor看下做了那些事情,默认进入CachedExecutor类:

看到,先对缓存进行查询,不存在则进入Executor实现类中的query方法,这里看下Executor是如何创建的,跟进Configuration中newExecutor:

可以看到mybaits这里使用装饰器模式通过CachedExecutor对Executor实现类进行包装,增加了缓存的功能。 -
看下Executor实现类的query方法:

实际进入RoutingStatementHandler的query()
RoutingStatementHandler将请求分发给不同的StatementHandler实现类:

看一下RoutingStatemnent的类图:

典型的装饰器模式,其中StatementHandler有3中实现方式:分别对jdbc中的3中Statment进行包装:- SimpleStatementHandler:直接调用jdbc中的Statement;
- PreparedStatementHandler:调用jdbc的PreparedStatement,对sql进行预编译,其中参数化参训也会防止sql注入,在XMLStatementBuilder中默认使用PreparedType为Prepared;
- CallableStatementHandler:调用存储过程.
其中Mybaits中的拦截器也是在这里进行实现的。
-
这里通过RoutingStatementHandler分发到PreParedStatementHandler:

在ResultHandler中对元数据进行处理,返回查询结果:

至此,一次完成的查询过程就结束了。
小结
可以看到在sqlSession的一次调用中,mybaits通过一系列层级关系,将不同的业务逻辑通过不同的接口进行抽象,多次利用装饰器模式对业务中相同的功能调用进行统一处理,同时保证实现类的独立性。
最后通过StatementHandler和ResultHandler将JDBC调用数据处理进行逻辑分层。
了解更多请关注微信公众号


本文深入探讨了Mybatis的SqlSession生命周期,从SqlSessionFactory的生成到SqlSession的执行过程,包括Executor、StatementHandler和ResultSetHandler的角色。通过源码分析,揭示了Mybatis如何通过装饰器模式和接口分层实现数据库操作,以及防止SQL注入的机制。文章总结了SqlSession调用的整个流程,并强调了Mybatis设计模式的应用。
1064

被折叠的 条评论
为什么被折叠?



