You need to enable JavaScript to run this app. MyBatis如何为所有查询传递默认参数(Spring Boot加密解密场景)
优惠活动
大模型
产品
解决方案
定价
更多

MyBatis如何为所有查询传递默认参数(Spring Boot加密解密场景)

问题核心原因

当前参数无法传入查询的本质是MyBatis的取值机制不匹配:

  • MyBatis 配置类Configuration下的variables全局变量集合,仅支持${}语法的静态SQL文本替换逻辑,完全不会被#{}预编译参数占位符识别
  • 你SQL里写的#{secretKey}属于预编译参数绑定逻辑,运行时只会从Mapper方法入参、@Param标注的参数值中查找匹配项,根本不会读取全局变量里存的内容,自然会取不到值。

你原来编写的configuration.getVariables().put("secretKey", "my secret key")这段配置逻辑本身没有问题,只是和SQL里的取值语法不匹配。

可落地的实现方案

方案1:适配全局变量的语法要求

如果不想调整Java侧的拦截器、Mapper方法定义,只需要把SQL里对应位置的#{secretKey}改成${secretKey}即可,改完的SQL示例如下:

select
         a.ID,
         CAST(AES_DECRYPT(a.FIRST_NAME, SHA2(${secretKey}, 512)) AS CHAR) FIRST_NAME,
         CAST(AES_DECRYPT(a.LAST_NAME, SHA2(${secretKey}, 512)) AS CHAR) LAST_NAME,
         USERNAME,
         PASSWD,
         b.ID ID_ROLE,
         b.NAME ROLE_NAME
       from users a join
       roles b on a.ID_ROLE = b.ID
       where
        USERNAME = #{username,jdbcType=VARCHAR} 

这个方案的注意事项:

  • 因为${}是直接把变量值拼到SQL文本里,你这里的secretKey是服务端自定义的固定配置值,并非外部用户传入的内容,不存在SQL注入风险
  • 这种方式的局限是全局变量在应用启动时就会加载到MyBatis配置里,如果后续修改secretKey值需要重启应用才能生效

方案2:通过MyBatis拦截器统一注入预编译参数(推荐)

如果不想用文本拼接的${}语法,希望走#{}的预编译参数绑定逻辑,可以自定义MyBatis参数拦截器,统一为所有目标表的select查询注入secretKey参数,完全不用修改每个Mapper方法的入参定义。
实现逻辑要点:

  • 拦截器匹配所有涉及目标加密表的select查询操作
  • 从Spring配置上下文读取实时的secretKey值,动态注入到当前查询的参数Map中
  • 让SQL里原有的#{secretKey}能正常从参数上下文匹配到值,完成预编译参数绑定

这个方案的优势是可以保留预编译的类型安全特性,同时支持从配置中心读取动态secretKey、无需重启就可以更新值,最适配你“为某张表的所有select查询统一传默认解密参数”的需求。

常见避坑点
  • 不要混淆#{}和${}的取值范围:#{}是运行时参数绑定,只匹配Mapper入参、拦截器动态注入的参数;${}是静态文本替换,可匹配全局配置变量、SQL片段引用
  • 不要把全局变量的值设置成外部可传入的内容,避免触发SQL注入风险

内容的提问来源于stack exchange,提问作者HK15

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.11.04 04:54:00