Spring+Hibernate+Oracle19c环境ojdbc8传空查询参数报错咨询
问题根因分析
该错误是ojdbc 19.3~19.8版本的已知缺陷,触发位置为客户端结果集缓存的空参数缓存Key计算逻辑,DynamicByteArray类的updateDigest方法对空值的边界处理异常,直接触发断言报错。
仅JUnit场景触发的原因:测试环境通常会默认开启JDBC语句隐式缓存来提升单测执行效率,而生产环境未开启该配置,不会触发缓存逻辑因此不会报错。
解决方案
按优先级从高到低排列:
- 方案1:升级ojdbc驱动版本
直接将ojdbc8驱动升级到19.11.0.0及以上版本即可,该缺陷在高版本中已被Oracle官方修复,无需修改任何业务代码和配置。 - 方案2:禁用Oracle JDBC隐式语句缓存
无需升级驱动,在JDBC连接配置中添加参数即可生效:
如果你使用Spring配置,在数据源的连接属性中添加以下配置(以SpringBoot+Hikari连接池为例):
单测场景也可以直接在测试的JVM启动参数中添加spring: datasource: hikari: data-source-properties: oracle.jdbc.implicitStatementCacheSize: 0-Doracle.jdbc.implicitStatementCacheSize=0。 - 方案3:代码层规避
如果你暂时无法修改驱动和配置,可以调整查询逻辑规避空参数场景:
也可以调整查询语句使用// 原生查询示例 @Override public BigDecimal testQueryNativeEmpty(String empty) { // 空参数直接返回符合业务逻辑的默认值,跳过空参数查询 if (empty == null || empty.isEmpty()) { return BigDecimal.ZERO; } StringBuilder queryString = new StringBuilder("SELECT count(1) from silab.system_param sp "); queryString.append("where sp.spm_code = :empty "); Query query = entitymanager.createNativeQuery(queryString.toString()); query.setParameter("empty", empty); return (BigDecimal) query.getSingleResult(); }NVL函数统一处理空值,避免传入空参数触发缓存缺陷:SELECT count(1) from silab.system_param sp where nvl(sp.spm_code, ' ') = nvl(:empty, ' ')
内容的提问来源于stack exchange,提问作者Martel Benjamin
相关产品推荐
相关产品推荐

