Mybatis中SqlNode的组合模式

本文深入探讨了Mybatis中SqlNode如何运用组合模式构建动态SQL。SqlNode作为容器,包含等节点,通过TextSqlNode、IfSqlNode、TrimSqlNode、ForEachSqlNode等实现动态SQL的构建。DynamicContext、BindingTokenParser和OgnlCache等在解析和优化过程中起关键作用。
摘要由CSDN通过智能技术生成

组合( Composite )模式就是把对象组合成树形结构,以表示“部分-整体”的层次结构,用户可以像处理一个简单对象一样来处理一个复杂对象,从而使得调用者无需了解复杂元素的内部结构。

组合模式中的角色有:

  • 抽象组件(容器):定义了树形结构中所有类的公共行为,例如add(),remove()等方法。

  • 树叶:最终实现类,没有子类。

  • 树枝:有子类的管理类,并通过管理方法调用其管理的子类的相关操作。

  • 调用者:通过容器接口操作整个树形结构。

具体组合模式的例子可以参考 设计模式整理

现在我们来说一下SqlNode是什么,来看这么一段配置文件

<select id="findByGameTypeCount" resultType="java.lang.Long">   select count(*)
   from betdetails a inner join UserBetOrder b on a.orderId = b.id   <where>      <if test="gameType != null and gameType > 0">         a.gameType = #{gameType} and      </if>      <if test="currDrawno != null">         b.currentDrawno = #{currDrawno} and      </if>      <if test="orderId != null and orderId > 0">         a.orderId = #{orderId} and      </if>      <if test="status != null and status >= 0">         a.status = #{status} and      </if>      <if test="userId != null and userId > 0">         b.userId = #{userId} and      </if>      <if test="start != null">         a.createTime &gt;= #{start} and      </if>      <if test="end != null">         a.createTime &lt;= #{end} and      </if>      1 = 1   </where></select>
<insert id="insertBetdetailsByBatch" parameterType="java.util.List">   insert into betdetails(id,orderId,actorIndex,createTime,ballIndex,ballValue,betAmount,rate1,rate2,rate3,gameType,status,betResult,awardAmount,ballName) values   <foreach collection="list" item="item" index="index" separator=",">      (#{item.id},#{item.orderId},#{item.actorIndex},#{item.createTime},#{item.ballIndex},#{item.ballValue},#{item.betAmount},#{item.rate1},#{item.rate2},#{item.rate3},#{item.gameType},#{item.status},#{item.betResult},#{item.awardAmount},#{item.ballName})   </foreach></insert>

这其中的<if><where><foreach>节点就是SqlNode节点,SqlNode是一个接口,代表着组合模式中的容器。只要是有SqlNode,那就代表着一定是一个动态的SQL,里面就有可能会有参数#{}

public interface SqlNode {
  //SqlNode接口中定义的唯一方法,该方法会根据用户传入的实参,解析该SqlNode所记录的动态SQL节点,并调用DynamicContext.appendSql()方法将解析后的SQL片段追加到
  //DynamicContext.sqlBuilder中保存
  //当SQL节点下的所有SqlNode完成解析后,就可以从DynamicContext中获取一条动态生成的完整的SQL语句  boolean apply(DynamicContext context);}

我们先来看一下DynamicContext是什么,它的核心字段如下

private final ContextMap bindings; //参考上下文
//在SqlNode解析动态SQL时,会将解析后的SQL语句片段添加到该属性中保存,最终拼凑出一条完成的SQL语句private final StringBuilder sqlBuilder = new StringBuilder();

ContextMap是一个内部类,继承于HashMap,重写了get方法

static class ContextMap extends HashMap<String, Object> {  private static final long serialVersionUID = 2977601501966151582L;  //将用户传入的参数封装成MetaObject对象(类实例中检查类的属性是否包含getter,setter方法)  private MetaObject parameterMetaObject;  public ContextMap(MetaObject parameterMetaObject) {    this.parameterMetaObject = parameterMetaObject;  }  @Override  public Object get(Object key) {
    String strKey = (String) key;
    //如果ContextMap中已经包含了该key,则直接返回
    if (super.containsKey(strKey)) {     
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值