我们来详细解释一下:在 Java 中,"将租户 ID 包装为 JSQLParser 的 StringValue 表达式对象" 中的 JSQLParser
到底是什么?
✅ 一、JSQLParser 是什么?
JSQLParser 是一个 Java 开源库 ,用于 解析、修改和生成 SQL 语句。
- 官网:https://github.com/JSQLParser/JSqlParser
- 功能:将 SQL 字符串解析成 Java 对象树(AST,抽象语法树),让你可以在代码中 读取、修改、重构 SQL
- 常见用途:
- SQL 解析器
- SQL 重写(如多租户、分表分库、审计日志)
- MyBatis-Plus、ShardingSphere 等框架底层依赖它
✅ 二、为什么需要"将租户 ID 包装为 StringValue"?
你提到的这行代码:
return new StringValue(headerValue);
出现在 MyBatis-Plus 多租户插件 的 TenantLineHandler
实现中。
它的目的是:在 SQL 的 WHERE 条件中自动加上 tenant_id = 'xxx'
,实现数据隔离。
但 MyBatis-Plus 不是直接拼字符串,而是通过 JSQLParser 解析 SQL,然后插入表达式对象。
所以,它需要你返回一个 JSQLParser 定义的表达式对象 ,而不是简单的 String
。
✅ 三、StringValue 是什么?
net.sf.jsqlparser.expression.StringValue
是 JSQLParser 提供的一个类,表示 SQL 中的一个字符串值。
举个例子:
你想让 SQL 变成:
SELECT * FROM user WHERE tenant_id = 'tenant_001';
其中 'tenant_001'
就是一个字符串值。
在 JSQLParser 中,这个值不能用 Java 的 String
,而要用:
new StringValue("tenant_001")
这样 JSQLParser 才能正确地把它插入到 SQL 的 AST(抽象语法树)中。
✅ 四、完整流程示例
假设你有:
@Override
public Expression getTenantId() {
String tenantId = HttpHeaderUtil.getHeaderValue("tenant-id");
if (tenantId == null) {
return null;
}
return new StringValue(tenantId); // ← 包装成 JSQLParser 的表达式
}
执行过程:
-
用户请求头带
tenant-id: tenant_001
-
MyBatis-Plus 拦截 SQL:
SELECT * FROM user WHERE name = 'zhangsan'
-
JSQLParser 解析 SQL 成对象树
-
框架调用
getTenantId()
→ 返回new StringValue("tenant_001")
-
框架生成表达式:
tenant_id = 'tenant_001'
-
修改 SQL 为:
SELECT * FROM user WHERE name = 'zhangsan' AND tenant_id = 'tenant_001'
-
执行最终 SQL
✅ 五、JSQLParser 常见表达式类
Java 类 | 表示的 SQL 部分 | 示例 |
---|---|---|
StringValue("abc") |
字符串值 | 'abc' |
LongValue(123) |
长整型值 | 123 |
DoubleValue(3.14) |
浮点数 | 3.14 |
Column("tenant_id") |
列名 | tenant_id |
EqualsTo(col, val) |
等于条件 | tenant_id = 'abc' |
AndExpression(...) |
AND 条件 | A = 1 AND B = 2 |
✅ 六、依赖引入(Maven)
如果你的项目用了 MyBatis-Plus 的多租户功能,通常已经间接引入了 JSQLParser。
你也可以显式引入:
<dependency>
<groupId>com.github.jsqlparser</groupId>
<artifactId>jsqlparser</artifactId>
<version>4.7</version> <!-- 使用最新稳定版 -->
</dependency>
✅ 七、总结
问题 | 回答 |
---|---|
JSQLParser 是什么? | 一个 Java SQL 解析库,能把 SQL 解析成对象,支持修改和重建 |
为什么要用 StringValue ? |
因为 MyBatis-Plus 多租户插件通过 JSQLParser 修改 SQL,需要标准表达式对象 |
new StringValue("xxx") 做了什么? |
把租户 ID 包装成 SQL 中的字符串值,用于生成 tenant_id = 'xxx' 条件 |
不用它行不行? | 不行,必须返回 Expression 子类,否则多租户不生效或报错 |
✅ 一句话总结:
JSQLParser 是一个 SQL 解析引擎,
StringValue
是它用来表示 SQL 中字符串值的对象;在多租户场景中,我们需要把租户 ID 包装成StringValue
,以便 MyBatis-Plus 能安全地将tenant_id = 'xxx'
插入到 SQL 中。