Spring Boot 3.2迁移后Hibernate 6原生查询空参数报错求助
问题描述
从Spring Boot 2.7迁移至3.2后,使用Spring Data JPA执行原生查询时,当mySecondField参数为null时触发以下SQL语法错误:
Caused by: org.hibernate.exception.SQLGrammarException: JDBC exception executing SQL [
SELECT *
FROM myTable
WHERE (? IS NULL OR my_first_field like ? || '%')
AND (? IS NULL OR my_second_field like ? || '%')
LIMIT ?
] [ERROR: could not determine data type of parameter $3] [n/a]
对应的JpaRepository查询代码如下:
@Query( value = """ SELECT * FROM myTable WHERE (:myFirstField IS NULL OR my_first_field like :myFirstField || '%') AND (:mySecondField IS NULL OR my_second_field like :mySecondField || '%') LIMIT :limit """, nativeQuery = true) List<MyTableEntity> getEntitiesWhereFirstAndSecondFieldsLike( @Param("myFirstField") String myFirstField, @Param("mySecondField") String mySecondField, @Param("limit") int limit);
该查询在Spring Boot 2.7中正常运行,直接在PostgreSQL中替换参数为null执行也无问题。手动为参数添加类型转换(如:mySecondField as text)可临时解决,但不想逐个修改所有原生查询。
解决方案:配置Hibernate自动推断null参数类型
在Spring Boot配置文件中添加以下参数,让Hibernate为null参数自动指定对应JDBC类型:
application.properties
# 为String类型null参数指定VARCHAR类型 spring.jpa.properties.hibernate.type.preferred_null_jdbc_type_for_strings=VARCHAR # 可为其他类型添加对应配置,比如整数类型 spring.jpa.properties.hibernate.type.preferred_null_jdbc_type_for_primitives=INTEGER
application.yml
spring: jpa: properties: hibernate: type: # 为String类型null参数指定VARCHAR类型 preferred_null_jdbc_type_for_strings: VARCHAR # 可为其他类型添加对应配置,比如整数类型 preferred_null_jdbc_type_for_primitives: INTEGER
如果项目中存在其他类型的null参数(如日期、布尔值等),可添加对应的配置项,例如日期类型可设置为TIMESTAMP。
问题根源
Spring Boot 3.x升级了Hibernate版本(从5.x到6.x),Hibernate 6.x对原生查询的参数处理逻辑做了调整:当参数为null时,不再自动根据Java类型推断JDBC类型,导致PostgreSQL无法识别参数类型,从而抛出错误。而Hibernate 5.x(Spring Boot 2.7使用的版本)会自动完成类型推断,因此不会出现该问题。
内容的提问来源于stack exchange,提问作者Valentin Soufflet

