【问题标题】:MyBatis - Nested Conditions in Where ClauseMyBatis - Where 子句中的嵌套条件
【发布时间】:2014-05-11 01:03:36
【问题描述】:

我在 MyBatis v3 mapper xml 中动态生成 where 子句。但是,放置括号确实很麻烦。有没有不使用 if 语句的更简单的方法来处理问题?

<where>
  <if test="filter != null">
    <choose>
      <when test="filter.lref != null">
        file.lref = #{filter.lref}
      </when>
      <otherwise>
        <!-- I don't want to use this -->
        <if test="filter.forLike != null || filter.forInt != null">
          ( 
        </if>
        <if test="filter.forLike != null" >
          subject LIKE #{filter.forLike}    
          OR requester_identifier LIKE #{filter.forLike}
          OR requester_name LIKE #{filter.forLike}
        </if>
        <if test="filter.forInt != null">
          OR file_id = #{filter.forInt}
        </if>

        <!-- I don't want to use this -->
        <if test="filter.forLike != null || filter.forInt != null">
          ) 
        </if>
      </otherwise>
    </choose>
  </if>
  <if test="listMode > 0">
    <choose>
       <when test="listMode == 1">
         AND file_status_link.dosya_ref is not NULL
       </when>
       <otherwise>
         AND file_status_link.dosya_ref is NULL
       </otherwise>
    </choose>
   </if>            
</where>

动态生成的SQL输出示例如下

WHERE ( subject LIKE ? OR requester_identifier LIKE ? OR requester_name LIKE ? ) 
AND file_status_link.dosya_ref is NULL 

【问题讨论】:

    标签: ibatis mybatis


    【解决方案1】:

    您可以尝试将该部分封装在&lt;trim&gt; 标记中。应该是这样的:

    <trim prefix="(" prefixOverrides="OR" suffix=")">
      <if test="filter.forLike != null" >
        subject LIKE #{filter.forLike}    
        OR requester_identifier LIKE #{filter.forLike}
        OR requester_name LIKE #{filter.forLike}
      </if>
      <if test="filter.forInt != null">
        OR file_id = #{filter.forInt}
      </if>
    </trim>
    

    【讨论】:

    • 你是对的@partlov。但它没有解决问题:(当filter.forLike为空时OR不会被清除。你的建议是处理这种情况所必需的。如果filter.forLikefilter.forInt都是空的,如果我们删除不需要 if 子句,那么 SQL 输出是:WHERE ( ) AND file_status_link.dosya_ref is NULL 无论如何,trim 仍然是解决问题的最接近的选项。
    • 根据您的编辑,我们彼此不理解。删除您的两个if 原因。如果需要,Trim 会自动添加 ()。 id OR 也是 &lt;trim&gt; 中的第一个单词,它应该替换为 ( - 这是由 prefixOverrides 完成的。
    • 现在我完全理解并应用了您的解决方案,感谢您的澄清。 Trim 同时执行两项工作: 1. 如果底层字符串为空,则清理前缀-后缀。 2. 如果基础字符串以它们开头,则删除覆盖的关键字。谢谢。
    【解决方案2】:

    伪 SQL (XML-SQL):

    where
        1 = 1
        <A>and file.lref = #{filter.lref}</A>
        <D>and (
            <E>
            subject like #{filter.forLike}    
            or requester_identifier like #{filter.forLike}
            or requester_name like #{filter.forLike}
            </E>
            <F>or file_id = #{filter.forInt}</F>
        )</D>
        </B>
        <C>and file_status_link.dosya_ref is <G>not</G> null</C>
    

    地点:

    A: <B> && filter.lref != null
    B: filter != null
    D: <B> && (<E> || <F>)
    E: filter.forLike != null
    F: filter.forInt != null
    C: listMode > 0
    G: listMode == 1
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-08-24
      • 1970-01-01
      • 1970-01-01
      • 2021-07-05
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多