ibatis动态表名用"$""#"

本文介绍了在Ibatis中使用#和$的不同之处。当使用#时,Ibatis会在变量前后添加单引号,适用于表名等需要特殊处理的情况;而使用$时则直接将变量值插入SQL语句中,适用于不需要特殊处理的场景。

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

这就涉及到“#”和“$”的区别了,一时半会儿也说不好,举个简单的例子吧

假设你传入的变量tableName = "table1"的话

那么在你写的ibatis表达式
INSERT INTO #tableName# VALUES(...) 
会被翻译成
INSERT INTO 'table1' VALUES(...)

如果写成
INSERT INTO $tableName$ VALUES(...)的话
就会翻译成
INSERT INTO table1 VALUES(...)

我的理解就是 用“#”的话,ibatis会在你的变量前后加上“'”(单引号),而用“$”的话,则不会加“'”(单引号) 
### 使用 MyBatis 拦截器实现动态表功能 为了实现在多租户环境中根据 `tenantId` 动态更改表的需求,可以利用 MyBatis 的拦截器机制来修改 SQL 语句中的表。下面是一个完整的解决方案。 #### 创建自定义拦截器类 创建一个新的 Java 类继承于 `Interceptor` 接口并重写其方法: ```java import org.apache.ibatis.executor.statement.StatementHandler; import org.apache.ibatis.plugin.*; import java.sql.Connection; @Intercepts({ @Signature(type = StatementHandler.class, method = "prepare", args = {Connection.class, Integer.class}) }) public class TenantTableInterceptor implements Interceptor { private static final String TENANT_ID_KEY = "TENANT_ID"; @Override public Object intercept(Invocation invocation) throws Throwable { // 获取原始SQL语句 StatementHandler statementHandler = (StatementHandler)invocation.getTarget(); MetaObject metaObject = SystemMetaObject.forObject(statementHandler); MappedStatement mappedStatement = (MappedStatement)metaObject.getValue("delegate.mappedStatement"); BoundSql boundSql = statementHandler.getBoundSql(); // 修改SQL语句中的表为带有租户ID前缀的形式 String originalSql = boundSql.getSql(); String tenantId = getTenantIdFromContext(); // 假设这里是从上下文中获取到的租户ID if(tenantId != null && !"".equals(tenantId.trim())) { String newSql = replaceTableNameWithTenantPrefix(originalSql, tenantId); metaObject.setValue("delegate.boundSql.sql", newSql); } return invocation.proceed(); } /** * 替换原SQL中的表为带租户前缀的新称 */ private String replaceTableNameWithTenantPrefix(String sql, String tenantId){ StringBuilder resultBuilder = new StringBuilder(sql.length()); int index = 0; while(index < sql.length()){ char c = sql.charAt(index++); if(c == &#39;`&#39; || c==&#39;[&#39;){ // 处理反引号或方括号包围的情况 int endIndex = sql.indexOf(&#39;]&#39;,index)>-1 ? sql.indexOf(&#39;]&#39;,index):sql.indexOf(&#39;`&#39;,index); if(endIndex>-1){ String tableName = sql.substring(index,endIndex).trim(); // 添加租户前缀 resultBuilder.append("`").append(tenantId.toLowerCase()).append("_").append(tableName).append("`"); index=endIndex+1; continue; } } resultBuilder.append(c); } return resultBuilder.toString(); } /** * 从线程局部变量或其他地方取得当前请求对应的租户ID */ protected abstract String getTenantIdFromContext(); } ``` 此代码片段展示了如何编写一个简单的 MyBatis 插件用于替换查询中的表[^1]。注意这里的 `getTenantIdFromContext()` 方法需要依据实际应用场景自行实现逻辑以获得当前操作所属的租户标识。 #### 注册插件配置 为了让上述拦截器生效,在 Spring Boot 应用程序中注册该插件即可: ```yaml mybatis: configuration: plugins: - com.example.TenantTableInterceptor # 替换成真实的包路径加类 ``` 或者也可以通过编程方式添加至 MyBatis 配置对象内: ```java @Configuration public class MyBatisConfig { @Bean public ConfigurationCustomizer myBatisConfigurationCustomizer() { return configuration -> { configuration.addInterceptor(new TenantTableInterceptor()); }; } } ``` 以上就是基于 MyBatis 拦截器技术实现动态调整表的一个实例教程以及最佳实践建议[^2]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值