在 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>