mybatis ${ } 内部如果有 #{} 变量占位,是可以正常解析的变量的

本文介绍了Apache MyBatis中DynamicSqlSource类的实现,涉及SQL解析和参数绑定过程。重点讲解了如何使用SqlNode解析动态SQL,并通过SqlSourceBuilder将参数占位符转换为实际值。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

package org.apache.ibatis.scripting.xmltags;
import org.apache.ibatis.builder.SqlSourceBuilder;
import org.apache.ibatis.mapping.BoundSql;
import org.apache.ibatis.mapping.SqlSource;
import org.apache.ibatis.session.Configuration;
public class DynamicSqlSource implements SqlSource {

private final Configuration configuration;
private final SqlNode rootSqlNode;

public DynamicSqlSource(Configuration configuration, SqlNode rootSqlNode) {
this.configuration = configuration;
this.rootSqlNode = rootSqlNode;
}

@Override
public BoundSql getBoundSql(Object parameterObject) {
DynamicContext context = new DynamicContext(configuration, parameterObject);
1、//先做sql解析
rootSqlNode.apply(context);
SqlSourceBuilder sqlSourceParser = new SqlSourceBuilder(configuration);
Class<?> parameterType = parameterObject == null ? Object.class : parameterObject.getClass();
2、 //在做参数绑定
SqlSource sqlSource = sqlSourceParser.parse(context.getSql(), parameterType, context.getBindings());
BoundSql boundSql = sqlSource.getBoundSql(parameterObject);
context.getBindings().forEach(boundSql::setAdditionalParameter);
return boundSql;
}
}

1、sql解析,具体可以用如下的解析器
在这里插入图片描述
其中$在TextSqlNode 进行解析。

2、解析完毕后由后续的SqlSourceBuilder sqlSourceParser = new SqlSourceBuilder(configuration);
进行参数映射
SqlSource sqlSource = sqlSourceParser.parse(context.getSql(), parameterType, context.getBindings());

替换参数占位符#{} -> ?. 并且收集参数。

故: ${ } 内部如果有 #{} 变量占位,是可以正常解析的。

### MyBatis 中 `$` 和 `#` 的区别 在 MyBatis 中,`${}` 和 `${}` 是两种占位符语法,用于处理 SQL 动态拼接中的变量替换。以下是它们的区别: #### 1. **基本概念** - **`#{}`**: 这是一个预编译的占位符,在执行 SQL 前会被替换成一个 JDBC 参数占位符 (`?`) 并传递给数据库驱动程序进行安全绑定[^1]。 - **`${}`**: 这是一种字符串替换机制,直接将表达式的值插入到 SQL 字符串中,不会经过任何转义或安全性检查。 #### 2. **安全性对比** - 使用 `#{}` 可有效防止 SQL 注入攻击,因为它的值被当作参数而不是原始 SQL 部分来解析和执行。 - 而 `${}` 则会直接将变量值嵌入到 SQL 中,如果输入未经过滤,则可能导致严重的 SQL 注入风险[^3]。 #### 3. **适用场景** - 当需要构建动态表名、列名或者某些固定的 SQL 片段时,可以使用 `${}`,因为它允许更灵活的字符串操作。 - 对于大多数情况下涉及用户数据的操作(如条件过滤),推荐使用 `#{}` 来提高代码的安全性和可维护性[^4]。 #### 示例代码 下面展示了两者使用的具体例子: ```xml <!-- 使用 #{param} --> <select id="selectUsers" resultType="User"> SELECT * FROM users WHERE status = #{status} </select> <!-- 使用 ${param}, 注意这里假设 tableName 已经验证过 --> <select id="selectByTableName" resultType="map"> SELECT * FROM ${tableName} </select> ``` 上述第一个示例利用了 `#{status}` 安全地传参;第二个则通过 `${tableName}` 实现了动态表切换功能[^5]。 ### 总结 总之,在实际开发过程中应优先考虑采用 `#{}` 方式以保障应用程序免受恶意注入威胁的同时还能获得更好的性能表现。只有当确实存在特殊需求无法单纯依靠问号占位完成任务的时候才谨慎选用 `${}` 方法来进行相应处理。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值