如何利用Optional.ofNullable实现在MyBatis拦截器中处理动态变量参数

风婷姑娘_1262

风婷姑娘_1262

2026-05-14

158人浏览

原创

Optional.ofNullable用于安全封装可能为null的动态参数,避免空指针;需在拦截器或Provider中解包为原始值使用,不可直接传入MyBatis参数映射或#{}表达式。

如何利用optional.ofnullable实现在mybatis拦截器中处理动态变量参数

在 MyBatis 拦截器中处理动态变量参数时,Optional.ofNullable 本身不直接参与 SQL 解析或参数替换,但它能帮你安全地封装和传递可能为 null 的动态参数,避免空指针、提升拦截器逻辑健壮性。关键在于:**用它包装待处理的参数对象(如 Map、DTO、表达式上下文),再在拦截器中统一判空与解包,而非裸写 if (obj != null)。**

拦截器中用 Optional 包装动态参数上下文

MyBatis 动态参数通常来自 BoundSql.getAdditionalParameters()(如 #{} 中的表达式结果)或自定义插件传入的上下文对象。这些值可能是 null,尤其在条件未命中时。

建议在插件入口(如 intercept(Invocation invocation))中,将易空参数封装为 Optional:

  • 若参数是 Map 类型(如 additionalParameters),可封装为 Optional>,后续用 .map(m -> m.get("xxx")) 安全取值
  • 若你扩展了 InterceptorContext 类来携带运行时变量(如租户 ID、时间偏移),让该类构造器接受 Optional tenantId,内部用 tenantId.orElse("default") 提供默认值
  • 避免在拦截器里反复判空,把判空逻辑收敛到 Optional 的链式调用中,比如:
      Optional.ofNullable(context).map(c -> c.getTenant()).filter(t -> !t.isEmpty()).orElse("public");

结合 @SelectProvider/@UpdateProvider 的动态 SQL 变量注入

当使用 @SelectProvider 方法生成 SQL 时,Provider 方法接收的参数常为 Map 或自定义对象。这些参数中的 key 可能缺失或值为 null,导致 ${} 表达式报错或拼出非法 SQL。

可在 Provider 方法内用 Optional.ofNullable 统一兜底:

  • String orderBy = Optional.ofNullable(params.get("orderBy")).map(Object::toString).orElse("id");
  • Integer limit = Optional.ofNullable(params.get("limit")).filter(v -> v instanceof Number).map(v -> ((Number)v).intValue()).orElse(10);
  • 对布尔型开关(如 isAuditEnabled),用 Optional.ofNullable(...).orElse(false) 明确语义,比 (Boolean)params.get("x") == true 更安全

拦截 BoundSql 并安全重写 SQL 片段

若需在拦截器中修改 SQL(如自动添加租户条件),需解析 BoundSql.getSql() 或操作 ParameterMapping。此时动态变量(如租户字段名、值)很可能来自线程上下文或配置中心,极易为 null。

推荐做法:

  • 将租户字段名、值分别封装为 Optional tenantCol 和 Optional tenantVal
  • 用 tenantCol.flatMap(col -> tenantVal.map(val -> " AND " + col + " = ?")) 构建追加条件,整个表达式天然支持空值跳过
  • 若最终需要插入占位符参数,用 tenantVal.ifPresent(val -> newParams.add(val)) 安全添加,不触发 NPE

注意:Optional 不是万能胶,别滥用

Optional 是容器,不是数据类型。它不能序列化进 MyBatis 参数映射,也不能直接传给 JDBC 驱动。所有 Optional 必须在进入 SQL 构建/执行前解包为原始值。

常见误用:

  • 把 Optional 当作参数 put 进 Map 传给 Mapper —— MyBatis 无法识别,会报 Property 'get' not found
  • 在 #{} 表达式里写 #{optionalValue.orElse("a")} —— MyBatis 不解析 Java 方法调用,仅支持属性访问
  • 过度嵌套 Optional.ofNullable(a).map(...).flatMap(...).orElse(...) 导致可读性下降 —— 此时不如拆成清晰的 if-else 或提取方法
PHP速学视频免费教程(入门到精通)
PHP速学视频免费教程(入门到精通)

PHP怎么学习?PHP怎么入门?PHP在哪学?PHP怎么学才快?不用担心,这里为大家提供了PHP速学教程(入门到精通),有需要的小伙伴保存下载就能学习啦!

下载

相关标签:

本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

相关专题

更多
java
java

Java是一个通用术语,用于表示Java软件及其组件,包括“Java运行时环境 (JRE)”、“Java虚拟机 (JVM)”以及“插件”。php中文网还为大家带了Java相关下载资源、相关课程以及相关文章等内容,供大家免费下载使用。

2023.06.15

11777

6

java正则表达式语法
java正则表达式语法

java正则表达式语法是一种模式匹配工具,它非常有用,可以在处理文本和字符串时快速地查找、替换、验证和提取特定的模式和数据。本专题提供java正则表达式语法的相关文章、下载和专题,供大家免费下载体验。

2023.07.05

8862

9

java自学难吗
java自学难吗

Java自学并不难。Java语言相对于其他一些编程语言而言,有着较为简洁和易读的语法,本专题为大家提供java自学难吗相关的文章,大家可以免费体验。

2023.07.31

7612

8

java配置jdk环境变量
java配置jdk环境变量

Java是一种广泛使用的高级编程语言,用于开发各种类型的应用程序。为了能够在计算机上正确运行和编译Java代码,需要正确配置Java Development Kit(JDK)环境变量。php中文网给大家带来了相关的教程以及文章,欢迎大家前来阅读学习。

2023.08.01

1244

3

java保留两位小数
java保留两位小数

Java是一种广泛应用于编程领域的高级编程语言。在Java中,保留两位小数是指在进行数值计算或输出时,限制小数部分只有两位有效数字,并将多余的位数进行四舍五入或截取。php中文网给大家带来了相关的教程以及文章,欢迎大家前来阅读学习。

2023.08.02

1008

3

java基本数据类型
java基本数据类型

java基本数据类型有:1、byte;2、short;3、int;4、long;5、float;6、double;7、char;8、boolean。本专题为大家提供java基本数据类型的相关的文章、下载、课程内容,供大家免费下载体验。

2023.08.02

1496

5

java有什么用
java有什么用

java可以开发应用程序、移动应用、Web应用、企业级应用、嵌入式系统等方面。本专题为大家提供java有什么用的相关的文章、下载、课程内容,供大家免费下载体验。

2023.08.02

3089

5

java在线网站
java在线网站

Java在线网站是指提供Java编程学习、实践和交流平台的网络服务。近年来,随着Java语言在软件开发领域的广泛应用,越来越多的人对Java编程感兴趣,并希望能够通过在线网站来学习和提高自己的Java编程技能。php中文网给大家带来了相关的视频、教程以及文章,欢迎大家前来学习阅读和下载。

2023.08.03

20331

3

配置java环境变量
配置java环境变量

配置Java环境变量是为了让操作系统能够识别和使用Java的相关命令和功能。本专题为大家提供配置java环境变量相关文章,帮助大家解决问题。

2023.08.03

1355

8

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
热门推荐
/
最新课程
phpStudy极速入门视频教程
phpStudy极速入门视频教程

共6课时 | 54.7万人学习

独孤九贱(4)_PHP视频教程
独孤九贱(4)_PHP视频教程

共89课时 | 134.1万人学习