问题描述:
对象:数据库中一个字段addressJson,存储地址对象数组的JSON串;
对象示例:
[{"addressType":"1","inputType":"1","provinceCode":"140000","province":"山西省","selectOption":["140000","140100","140101"],"selectOptionStr":"山西省/太原市/市辖区","addressDetails":"","mapAddress":"","coordinate":"","overseaAddress":""},{"addressType":"1","inputType":"1","provinceCode":"130000","province":"河北省","selectOption":["130000","130200","130203"],"selectOptionStr":"河北省/唐山市/路北区","addressDetails":"","mapAddress":"","coordinate":"","overseaAddress":""}]
需求:这个字段中可能有多个地址对象,需要将多个地址对象拆解出来,并将这多个对象中的province字段单独提取出来;
解决方案:
实现思路:博主使用的是Oracle数据库,支持使用关键字JSON_TABLE来解析存储JSON数据类型的字段,可以使用这个关键字来提取字段中所有的地址对象,从而取出对象中的province字段;
具体实现:
SELECT *
FROM
TABLE_A t,
JSON_TABLE(
t.PROJECT_ADDRESS_JSON, -- JSON 字段
'$[*]' -- 表示 JSON 数组中的所有对象
COLUMNS (
ADDRESS_TYPE VARCHAR2(10) PATH '$.addressType', -- 提取 addressType
PROVINCE VARCHAR2(50) PATH '$.province' -- 提取 province
)
) jt
WHERER jt.ADDRESS_TYPE = 1 and jt.PROVINCE is not NULL;
新的问题:
上述代码写入mapper.xml文件后,访问时一直报错,错误信息如下:
Caused by: net.sf.jsqlparser.parser.ParseException: Encountered unexpected token: "(" "("
后查询网上博客后查询到了解决方案,需要在mapper接口文件的方法上加上注解@InterceptorIgnore(tenantLine = "1")即可解决,具体原理询问deepseek,回答如下,真实性见仁见智:
为什么添加
@InterceptorIgnore能解决问题?1. 多租户插件的干扰
- MyBatis-Plus 或其他框架的 租户拦截器 会自动在 SQL 中插入租户条件(如
AND tenant_id = xxx)。- 当你的 SQL 中包含复杂语法(如
JSON_TABLE)时,拦截器可能会错误地修改 SQL 结构,导致语法解析失败(如误在JSON_TABLE内部插入条件,破坏 JSON 路径表达式)。2.
@InterceptorIgnore的作用
@InterceptorIgnore(tenantLine = "1")的作用是 禁用当前 SQL 的租户拦截器,避免框架自动添加租户条件。- 禁用后,SQL 会按原样执行,不再被拦截器修改,因此
JSON_TABLE语法能正确解析。
关键点分析
场景 行为 结果 未加注解 租户拦截器尝试修改 SQL,可能在 JSON_TABLE内部插入条件破坏 JSON 语法,导致 ParseException添加注解 拦截器被禁用,SQL 保持原样 语法正确,执行成功
更深入的解决方案
如果不想全局禁用租户拦截器,可以进一步优化:
1. 检查租户拦截器的实现
- 确认拦截器是否支持忽略特定 SQL 片段(如通过注释标记)。
- 例如,MyBatis-Plus 的租户拦截器默认会忽略包含
@SqlParser(filter=true)的方法。2. 调整 SQL 写法
- 将
JSON_TABLE部分提取到子查询或嵌套查询中,减少拦截器误判的可能性。3. 升级框架版本
- 某些旧版拦截器对复杂 SQL 支持较差,升级 MyBatis-Plus 或其他相关库可能解决问题。
总结
根本原因:多租户拦截器错误地修改了包含
JSON_TABLE的 SQL,导致语法解析失败。解决方案:
- 使用
@InterceptorIgnore(tenantLine = "1")临时禁用拦截器(推荐)。- 长期方案:优化拦截器逻辑或升级框架版本。
这种方法既能保留多租户功能,又能兼容复杂 SQL 语法。