在 MyBatis 中,<bind> 标签是 XML 映射器中的一个元素,它允许你在 SQL 语句中使用动态表达式。<bind> 标签通常用于在映射文件中定义一个或多个变量,这些变量可以被用在同一映射文件中的 SQL 语句中。

示例

假设我们有一个需求,需要根据不同的用户的机构权限动态地添加过滤条件。

按照正常逻辑我们一般会使用 || 或者 concat进行拼接,SQL如下:

<if test='dto.companyCode != null and dto.companyCode!=""'>
            and m.company_code LIKE #{dto.companyCode} || '%'
        </if>

如果我们使用<bind> 标签则可以写成如下语法:

<if test='dto.companyCode != null and dto.companyCode!=""'>
            <bind name="companyCodeValue" value="dto.companyCode+'%'"/>
            and m.company_code LIKE #{companyCodeValue}
        </if>

错误示例

在 MyBatis 的 foreach 循环中使用 bind 元素时,需特别注意 bind 的作用域是当前整个 SQL 语句,而非单次循环迭代。这意味着在循环内多次使用 bind 绑定同名变量时,后一次会覆盖前一次的值,可能导致逻辑错误。

<if test='searchCompanies != null and searchCompanies.size > 0'>
            AND
            <foreach item="item" index="index" collection="searchCompanies" open="(" separator="OR" close=")">
                <bind name="searchCompanyCodeValue" value="item+'%'"/>
                m.company_code LIKE #{searchCompanyCodeValue}
            </foreach>
        </if>

根据以上示例,就会导致如果传进来的searchCompanies是[0352,0353,0354]

最终sql拼接就会变成:

and (m.company_code like '0354%'  OR  m.company_code like '0354%'  OR m.company_code like '0354%' )

按道理正常的脚本应该如下:

and (m.company_code like '0352%'  OR  m.company_code like '0353%'  OR m.company_code like '0354%' )

最终还是改回了正常的语法:

<if test='dto.searchCompanies != null and dto.searchCompanies.size > 0'>
            AND
            <foreach item="item" index="index" collection="dto.searchCompanies" open="(" separator="OR" close=")">
                m.company_code LIKE #{item} || '%'
            </foreach>
        </if>