You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Spring Boot 2.7.5升级后JPA参数绑定异常问题咨询

Spring Boot 2.7.5升级后LIKE子句NULL参数被绑定为空字符串的问题解决

问题重现

升级Spring Boot从2.7.4到2.7.5后,出现以下异常行为:

  • 使用=条件的查询中,NULL参数会被正常绑定为null
  • 使用LIKE子句的查询中,NULL参数被错误绑定为空字符串

示例对比:

  1. =条件查询:

    select user from User where :p_user_name is null or userName = :p_user_name
    

    参数绑定结果:

    binding parameter [1] as [VARCHAR] - [null]
    binding parameter [2] as [VARCHAR] - [null]
    
  2. LIKE条件查询:

    select user from User where :p_user_name is null or userName LIKE :p_user_name
    

    参数绑定结果:

    binding parameter [1] as [VARCHAR] - []
    binding parameter [2] as [VARCHAR] - []
    

原因分析

这个问题源于Spring Boot 2.7.5升级了Hibernate核心版本(从5.6.13.Final到5.6.14.Final),该版本的Hibernate对LIKE子句的NULL参数处理逻辑做了变更,自动将NULL转换为空字符串,导致原有查询逻辑失效。

解决方案

方案1:修改查询语句显式处理NULL

通过SQL函数或逻辑调整,确保NULL参数在LIKE子句中保留原有语义:

  • 如果需要在参数为NULL时匹配所有数据(原有逻辑),可以用COALESCE避免参数被转换:
    select user from User where :p_user_name is null or userName LIKE COALESCE(:p_user_name, '%')
    
  • 如果需要参数为NULL时匹配userName为NULL的记录,调整查询逻辑:
    select user from User where (:p_user_name is null and userName is null) or (userName LIKE :p_user_name)
    

方案2:自定义Hibernate类型保留NULL

创建自定义字符串类型,强制NULL参数在绑定过程中不被转换:

import org.hibernate.type.StringType;
import org.hibernate.type.descriptor.sql.VarcharTypeDescriptor;
import org.hibernate.engine.spi.SharedSessionContractImplementor;
import java.sql.PreparedStatement;
import java.sql.SQLException;

public class NullPreservingStringType extends StringType {
    @Override
    protected boolean registerUnderJavaType() {
        return true;
    }

    @Override
    public String getTypeName() {
        return "null-preserving-string";
    }

    @Override
    public void nullSafeSet(PreparedStatement st, Object value, int index, SharedSessionContractImplementor session) throws SQLException {
        if (value == null) {
            st.setNull(index, VarcharTypeDescriptor.INSTANCE.getSqlType());
        } else {
            super.nullSafeSet(st, value, index, session);
        }
    }
}

然后在配置文件中指定使用该类型:

spring.jpa.properties.hibernate.type.preferred_null_preserving_string_type=com.yourpackage.NullPreservingStringType

方案3:回退Hibernate版本

如果暂时无法修改代码,可以强制指定Hibernate版本回退到2.7.4对应的5.6.13.Final:

  • Maven:在dependencyManagement中添加:
    <dependencies>
        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-core</artifactId>
            <version>5.6.13.Final</version>
        </dependency>
    </dependencies>
    
  • Gradle:在dependencyManagement中配置:
    dependencies {
        dependency "org.hibernate:hibernate-core:5.6.13.Final"
    }
    

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.15 04:55:19