Optional.ofNullable用于安全封装可能为null的动态参数,避免空指针;需在拦截器或Provider中解包为原始值使用,不可直接传入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 - 用
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 或提取方法










