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参数被错误绑定为空字符串
示例对比:
=条件查询: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]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
相关产品推荐
相关产品推荐

