ibatis 3.0 Dynamic Sql 设计解析(并与2.x的差异)
前段时间ibatis3.0发布出来了,迫不及待,将其源码下载拜读。相对ibatis 2.x来说,3.0已是完全改变。具体我就不在这细说,论坛中有一个帖子介绍了ibatis 3.0的新特征及使用。
?? ? ?由于其他模块的源码我还未细读,在这篇中,先来讨论Dynamic Sql在ibatis 3.0中的实现并比较2.x对应模块的设计。
?
写在前头的话:
?? ? ?其实如从设计模式应用角度去看待ibatis 3.0中Dynamic Sql的实现,这篇跟我的上篇(HtmlParser设计解析(1)-解析器模式)相同,都是使用Interpreter模式。
?? ? ?这篇权当Interpreter模式的另一个demo,认我们体会这些开源项目中设计模式的使用。学习都是从模仿开始的,让 我们吸收高人们的经验,应用于我们实践项目需求中。
?
?? 从总结中提高:
?? 一、对比2.x中与3.0的Sqlmap中dynamic sql配置
?? 2.x:
??
?? 3.0:
??? ? ?从上面这个简单的比较中,第一感觉3.0了中其dynamic sql更加简洁明了。
?? ? ?其二,test="emailAddress != null" 添加了OGNL的解释支持,可以动态支持更多的判断,这将不限于原2.x中提供
的判断逻辑,更不需要为每个判断条件加个标签进行配置。
?? ? ?例如:<if test="id > 10 && id < 20"> ACC_EMAIL = #{emailAddress}</if>
?? ? ? ? ? ? ? <if test="Account.emailAddress != null "> ACC_EMAIL = #{emailAddress}</if> ……
?
?? 二、2.x Dynamic Sql的设计
?
???2.1、2.x中dynamic流程。
?? 这里帖出,我先前在分析ibatis 2.3时画的一个对dynamic sql的整体使用的时序图,可能会显得乱而复杂。
?? 2.2、主要类设计
?? ? ? 在这,我们只关注这几个类:XMLSqlSource、DynamicSql、SqlTagHandler (具体类结构图见后)
?? ? ?XMLSqlSource:相当于一个工厂类,其核心方法parseDynamicTags(),用于解析sql Tag,并判断是否是动态SQL标签。如果true,返回一个DynamicSql对象并创建多个SqlChildt对象添加至动态SQL列表中(addChild());false,返回RawSql对象(简单的SQL语句) 。
?? ? DynamicSql:核心的动态SQL类。其动态条件判断逻辑,参数映射等都发生在这个类中。
?? ? SqlTagHandle:动态条件判断接口,其每个动态SQL标签对应其一个子类。
??接下来,我们具体看下在DynamicSql类中核心方法。
?? ?DynamicSql:
??
????ConditionalTagHandler:
????
??有经验的人,我想一眼就能看出其3.0中的设计思想,从Test中可以看出,或者我上一篇介绍的HtmlParser NodeFilter。
?? ?YES,在ibatis 3.0 dynamic sql设计正是应用了解释器模式,替换了原在这种需求下相对显得笨拙的策略者模式。
?
?? 下面具体看下类结构图。
?
?? 3.2、类结构图
?? SqlNode Class?Diagram:
?? SqlSource Class?Diagram:
?
?? 3.3、配置文件的解析
?? 在这,我就顺便提下ibatis解析组件对dynamic sql的解析方式,以代码见分晓吧。
?
???XMLStatementBuilder:
??? ?上面是其解析代码的一部分,我想从这几行代码中,可以看出作者的思想了(遍历XML各节点,以节点名查找相应对应的处理器,分发之该处理器执行"业务分析" — 策略者模式,这样在XML中定义了多少标签,这里就需要多少个类与之对应,但如果策略类太多,这种方式就显得笨拙了)。
?
?? ?以下就是其核心类的一部分源码,先看再说。
?? ?3.4、DynamicSqlSource(核心类)
???public class MixedSqlNode implements SqlNode { ... ....public boolean apply(DynamicContext context) {//遍历组装的解析内容for (SqlNode sqlNode : contents) { // 转发至相关解释器处理sqlNode.apply(context); }return true;}}???IfSqlNode.class
Java代码 <