mybatis中bind的使用示例详解

 更新时间:2025年06月19日 16:33:03   作者:五月天的尾巴  
在 MyBatis 中,bind 标签允许在 OGNL 表达式上下文中创建一个变量并将其绑定到当前上下文,常用于动态 SQL 中简化复杂表达式或重复计算,这篇文章主要介绍了mybatis中bind的使用示例详解,需要的朋友可以参考下

mybatis中bind的使用

一、介绍

在 MyBatis 中,bind 标签允许在 OGNL 表达式上下文中创建一个变量并将其绑定到当前上下文,常用于动态 SQL 中简化复杂表达式或重复计算。

二、语法

<bind name="变量名" value="OGNL表达式"/>
  • name:变量名称,后续可直接引用。
  • value:OGNL 表达式,可以是字符串拼接、计算等操作。

三、常见示例

3.1、字符串拼接

在模糊查询中,避免直接在 SQL 中拼接 %,提升可读性:

<select id="searchUsers" resultType="User">
    <bind name="pattern" value="'%' + username + '%'"/>
    SELECT * FROM users 
    WHERE username LIKE #{pattern}
</select>

3.2、动态条件处理(三元表达式)

结合条件判断,简化复杂逻辑:

<select id="getUsers" resultType="User">
    <bind name="filterName" value="name != null ? name : '%'"/>
    SELECT * FROM users
    WHERE name LIKE #{filterName}
</select>

3.3、避免重复计算

在多次使用同一表达式时,通过 bind 复用:

<select id="calculate" resultType="double">
    <bind name="total" value="price * quantity"/>
    <bind name="discounted" value="total * (1 - discount)"/>
    SELECT #{discounted} AS final_price
</select>

3.4、bind与分页查询

bind经常与分页查询limit一起使用,用来计算limit中的起始条数与分页数。

<select id="pageListUser" resultType="com.demo.entity.User"
            parameterType="java.util.List">
    select * from user 
    where name = #{name}
    <if test="pageNo != null and pageSize != null">
        <bind name="pageNo" value="(pageNo-1)*pageSize"/>
        limit #{pageNo},#{pageSize}
    </if>
</select>
  • pageNo:页码、第几页
  • pageSize: 每页显示条数

3.5、foreach中使用bind

在 MyBatis 的 foreach 循环中,应避免使用 bind 来创建每个迭代的临时变量,因为 bind 的作用域是当前上下文,在循环中会被覆盖。替代方案是在 Java 代码中预处理数据,或者直接在表达式中使用循环项和索引。

若实在需要在foreach中使用bind,可以参考文末补充介绍《mybatis foreach里用bind、foreach中使用bind的坑、foreach中动态生成表名》

四、错误示例

4.1、where后面跟着bind

网上看到有些博文写过这样的示例,bind跟在where条件后面,但这是一种错误的写法。bind 变量仅在当前语句块(如 <select><update>)内有效。

&lt;select id="getUsersByNameAndAge" resultType="User"&gt;
    SELECT * FROM users
    WHERE name = #{name} AND age &gt;= &lt;bind name="minAge" value="${minAge}" /&gt;
&lt;/select&gt;

<bind> 必须放在 SQL 语句的最前面,不能跟在 WHERE 条件后面。

五、总结

5.1、注意事项

  • bind 变量仅在当前语句块(如 <select><update>)内有效。
  • OGNL 表达式支持 Java 语法,如三元运算符、方法调用等。
  • 优先使用 bind 而非直接拼接 SQL,以提高安全性和可维护性。

通过灵活使用 bind,可以显著提升 MyBatis 动态 SQL 的可读性和简洁性。

补充:mybatis foreach里用bind、foreach中使用bind的坑、foreach中动态生成表名

mybatis foreach里用bind、foreach中使用bind的坑、foreach中动态生成表名

一、前言

在mybatis实际开发中遇到这样一个场景,foreach标签中需要动态生成一个表名,如t0,t1,t2…等等, 可以在dao层传入,也可以在foreach中用bind标签生成,这里我们介绍使用bind生成该变量。

示例如下:

dao层传入[张三、李四]。 mapper.xml中根据传入的列表个数使用foreach进行union all拼接,并且需要动态生成表名 t0、t1等等。最终拼接sql如下:

select * from(
	select * from user where name='张三' order by id
) t0
union all
select * from(
	select * from user where name='李四' order by id
) t1

二、解决方法/foreach中使用bind

下面为公共的UserService.java、UserMapper.java中的代码

UserService.java代码:

@Autowired
private UserMapper userMapper;
public List<User> selectByNameList(){
    userMapper.selectByNameList(Arrays.asList("张三","李四"));
    return null;
}

UserMapper.java代码:

public interface UserMapper  {
    List<User> selectByNameList(List<String> nameList);
}

2.1、方法一:#传参

UserMapper.xml代码

<select id="selectByNameList" resultType="com.demo.entity.User"
            parameterType="java.util.List">
    <foreach collection="list" item="item" separator="union all"  index="index">
        select * from (
            select * from user where name = #{item} order by id
        ) t#{index}
    </foreach>
</select>

日志如下:

==>  Preparing: select * from ( select * from user where name = ? order by id ) t? union all select * from ( select * from user where name = ? order by id ) t?
==> Parameters: 张三(String), 0(Integer), 李四(String), 1(Integer)

2.2、方法二:$传参 bind生成变量

UserMapper.xml代码

<select id="selectByNameList" resultType="com.demo.entity.User"
            parameterType="java.util.List">
    <foreach collection="list" item="item" separator="union all"  index="index">
        <bind name="tableName" value="'t' + index"></bind>
        select * from (
            select * from user where name = #{item} order by id
        ) ${tableName}
    </foreach>
</select>

日志如下:

==>  Preparing: select * from ( select * from user where name = ? order by id ) t0 union all select * from ( select * from user where name = ? order by id ) t1
==> Parameters: 张三(String), 李四(String)

注意:

  • ${}方式传参有sql注入问题,所以确保${}中的变量没有注入风险。

三、bind变量覆盖问题/错误示例

上面的示例中,我们在foreach标签内使用了bind绑定变量给tableName并且用${tableName}的方式获取值。如果我们是使用#{tableName}的方式获取值,会发现每次tableName的值都会是最后一个元素。

错误示例一:

<select id="selectByNameList" resultType="com.demo.entity.User"
            parameterType="java.util.List">
    <foreach collection="list" item="item" separator="union all"  index="index">
        <bind name="tableName" value="'t' + index"></bind>
        select * from (
            select * from user where name = #{item} order by id
        ) #{tableName}
    </foreach>
</select>

日志文件:

==>  Preparing: select * from ( select * from user where name = ? order by id ) ? union all select * from ( select * from user where name = ? order by id ) ?
==> Parameters: 张三(String), t1(String), 李四(String), t1(String)

错误示例二:循环内重复绑定同名变量

<foreach item="item" collection="list" separator=",">
  <!-- 错误:每次循环覆盖 previousItem,最终所有值相同 -->
  <bind name="previousItem" value="item" />
  #{previousItem}
</foreach>

四、总结

总结:在 MyBatis 的 foreach 循环中,应避免使用 bind 来创建每个迭代的临时变量,因为 bind 的作用域是当前上下文,在循环中会被覆盖。替代方案是在 Java 代码中预处理数据,或者直接在表达式中使用循环项和索引。

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

到此这篇关于mybatis中bind的使用的文章就介绍到这了,更多相关mybatis bind使用内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • 解决修改配置文件导致MySQL服务无法启动和停止且MySQL服务操作按钮变为灰色

    解决修改配置文件导致MySQL服务无法启动和停止且MySQL服务操作按钮变为灰色

    这篇文章主要介绍了解决修改配置文件导致MySQL服务无法启动和停止且MySQL服务操作按钮变为灰色问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2023-12-12
  • AlmaLinux 9 安装 MySQL 8.0.32的详细过程

    AlmaLinux 9 安装 MySQL 8.0.32的详细过程

    这篇文章主要介绍了AlmaLinux 9 安装 MySQL 8.0.32的相关知识,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2023-04-04
  • mysql配置SSL证书登录的实现

    mysql配置SSL证书登录的实现

    应国家等级保护三级安全要求,mysql 的 ssl 需要安全证书加密,本文主要介绍了mysql配置SSL证书登录,感兴趣的可以了解一下
    2021-09-09
  • mysql语句查询用户权限过程详解

    mysql语句查询用户权限过程详解

    这篇文章主要介绍了mysql语句查询用户权限过程详解,授予用户的权限可能分全局层级权限、数据库层级权限、表层级别权限、列层级别权限、子程序层级权限。,需要的朋友可以参考下
    2019-06-06
  • windows10系统安装mysql-8.0.13(zip安装) 的教程详解

    windows10系统安装mysql-8.0.13(zip安装) 的教程详解

    这篇文章主要介绍了windows10安装mysql-8.0.13(zip安装) 的教程,非常不错,具有一定的参考借鉴价值,需要的朋友可以参考下
    2018-11-11
  • Mysql数据库之索引优化

    Mysql数据库之索引优化

    MySQL凭借着出色的性能、低廉的成本、丰富的资源,已经成为绝大多数互联网公司的首选关系型数据库。本文给大家介绍mysql数据库之索引优化,感兴趣的朋友一起学习吧
    2016-03-03
  • 详解MySQL子查询(嵌套查询)、联结表、组合查询

    详解MySQL子查询(嵌套查询)、联结表、组合查询

    这篇文章主要介绍了MySQL子查询(嵌套查询)、联结表、组合查询,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2019-03-03
  • MySql索引详细介绍及正确使用方法

    MySql索引详细介绍及正确使用方法

    这篇文章主要介绍了MySql索引详细介绍及正确使用方法的相关资料,需要的朋友可以参考下
    2017-07-07
  • MySQL中TO_DAYS()函数详解与实际应用举例

    MySQL中TO_DAYS()函数详解与实际应用举例

    TO_DAYS函数是指从零开始到函数内时间的天数,下面这篇文章主要给大家介绍了关于MySQL中TO_DAYS()函数详解与实际应用的相关资料,文中通过代码介绍的非常详细,需要的朋友可以参考下
    2024-04-04
  • MySQL 使用开源审计插件示例详解

    MySQL 使用开源审计插件示例详解

    审计插件是包含在 MariaDB 中的,所以需要先下载 MariaDB 然后将 server_audit.so 审计插件 copy 出来,这篇文章主要介绍了MySQL 使用开源审计插件,需要的朋友可以参考下
    2023-08-08

最新评论