mybatis动态sql中的bind标签灵活使用

版权声明:https://blog.csdn.net/xianzhuo_sky https://blog.csdn.net/xianzhuo_sky/article/details/82417945

bind标签在mybatis官方文档中只有一句话和一个基本例子进行了介绍,下面是官方文档的介绍:

bind 元素可以从 OGNL 表达式中创建一个变量并将其绑定到上下文。比如:

<select id="selectBlogsLike" resultType="Blog">
  <bind name="pattern" value="'%' + _parameter.getTitle() + '%'" />
  SELECT * FROM BLOG
  WHERE title LIKE #{pattern}
</select>

value的值写OGNL表达式,OGNL表达式的使用不做过多说明,如果想在OGNL表达式中使用字符串

  1. 简单写法:用引号扩起来,到底使用单引号还是双引号是由外层引号决定的。
  2. 标准写法:用%{’’}或%{""}把表达式括起来,强制转成字符串。

在这里value=后面外层使用的双引号,所以内层单引号括起来的’%‘表示的就是字符串’%’

由上面的例子我们可以知道,bind标签的name属性填写一个参数名,value填写这个参数的值(使用OGNL表达式),bind标签写上后,在标签后面的上下文中使用的和bind标签name值同名的参数,它的值就会被替换为bind标签的value的值。如上面的例子中,在执行这条select语句时,#{pattern}的值就会为"’%’ + _parameter.getTitle() + ‘%’"计算执行后的值。

我在实际做项目的时候,遇到了这样的一种情况,在一条sql语句中,有多个地方需要用到一个同名的参数,而这个参数在这几个地方的值是不一样的。下面是我遇到的情况:

<sql id="queryListWhere">
  <where>
    <if test="bussinessOppotunityId!=null and bussinessOppotunityId!=''">
      and t.bussiness_oppotunity_id = #{bussinessOppotunityId}
    </if>
    <if test="companyId!=null and companyId!=''">
      and t.company_id = #{companyId}
    </if>
    <if test="languageId!=null and languageId!=''">
      and t.language_id = #{languageId}
    </if>
    <if test="currencyId!=null and currencyId!=''">
      and t.currency_id = #{currencyId}
    </if>
    <if test="supplierId!=null and supplierId!=''">
      and t.supplier_id = #{supplierId}
    </if>
    <if test="paymentConditionId!=null and paymentConditionId!=''">
      and t.payment_condition_id = #{paymentConditionId}
    </if>
    <if test="invoiceTypeId!=null and invoiceTypeId!=''">
      and t.invoice_type_id = #{invoiceTypeId}
    </if>
    <if test="createBy!=null and createBy!=''">
      and t.create_by = #{createBy}
    </if>
    <if test="delFlag!=null and delFlag!=''">
      <choose>
        <when test="delFlag == '21'">
          and t.del_flag = 2
          and not exists(select 1 from in_quotation where PURCHASE_CONFIRMATION_ID = t.id and DEL_FLAG &lt;= 2)
        </when>
        <when test="delFlag == '22'">
          and t.del_flag = 2
          and not exists(select 1 from in_purchase_contract where purchase_confirmation_id = t.id and del_flag &lt;= 2)
          and exists (select 1 from in_quotation where purchase_confirmation_id = t.id and del_flag = '2')
        </when>
        <otherwise>
          and t.del_flag in (${delFlag})
        </otherwise>
      </choose>
    </if>
  </where>
</sql>

这个queryListWhere会根据dao接口传递过来的参数来实现条件查询,然后我需要写这样一段代码

<select id="showCount" resultType="map">
  select
  (select count(*) from in_purchase_confirmation t <include refid="queryListWhere"></include>) waitAudit,
  (select count(*) from in_purchase_confirmation t <include refid="queryListWhere"></include>) waitQuote,
  (select count(*) from in_purchase_confirmation t <include refid="queryListWhere"></include>) waitContract
  from dual
</select>

这段代码的三个地方都引入了queryListWhere,没做修改的情况下,这三个地方都会获取到同样参数值。
在这条语句的情况下,delFlag参数都会从dao接口传来的参数获取到同样的值,这3个子查询会查询到同样的结果。
而我需要在这3个子查询中,delFlag参数的值是不同的。比如我需要在第一个子查询处,delFlag为1;第二个子查询处,delFlag为21;第三个子查询处,delFlag为22。

我曾尝试使用include标签下的property标签来解决这个问题

<select id="showCount" resultType="map">
  select
  (select count(*) from in_purchase_confirmation t <include refid="queryListWhere"><property name="delFlag" value="1"></property></include>) waitAudit,
  (select count(*) from in_purchase_confirmation t <include refid="queryListWhere"><property name="delFlag" value="21"></property></include>) waitQuote,
  (select count(*) from in_purchase_confirmation t <include refid="queryListWhere"><property name="delFlag" value="22"></property></include>) waitContract
  from dual
</select>

但是发现property标签并没有起到作用,delFlag还是会直接使用dao接口传来的参数。似乎在dao接口有参数传递过来的情况下,property标签就失效了,sql语句中的参数会直接使用dao接口传递过来的参数。

使用bind标签就解决了我的问题,完善后的代码如下:

<select id="showCount" resultType="map">
  select
  (select count(*) from in_purchase_confirmation t <bind name="delFlag" value="'1'" /> <include refid="queryListWhere"></include>) waitAudit,
  (select count(*) from in_purchase_confirmation t <bind name="delFlag" value="'21'" /> <include refid="queryListWhere"></include>) waitQuote,
  (select count(*) from in_purchase_confirmation t <bind name="delFlag" value="'22'" /> <include refid="queryListWhere"></include>) waitContract
  from dual
</select>

bind标签的name都是delFlag后写的bind标签会覆盖前面的bind标签

猜你喜欢

转载自blog.csdn.net/xianzhuo_sky/article/details/82417945
今日推荐