在适配过程中,发现部分sql报错 201 语法错误
报错信息如下
Hibernate: select * from Student where id in (? ) and name in (? ) and id in (? ) and name in ( )
2024-08-18 14:45:53.453 WARN 24396 --- [nio-9000-exec-1] o.h.engine.jdbc.spi.SqlExceptionHelper : SQL Error: -201, SQLState: 42000
2024-08-18 14:45:53.453 ERROR 24396 --- [nio-9000-exec-1] o.h.engine.jdbc.spi.SqlExceptionHelper : 发生语法错误。
简化代码片段如下
@Query(value="select * from Student where id in (:#{#selentity.total.size()} ) and name in (:#{#selentity.name} ) "+"" +
"and id in (:#{#selentity.total.size()} ) and name in (:#{#selentity.total} )",nativeQuery=true)
List<Student> queryByNameUseJPQL(Selentity selentity);
分析sql 发现 最后一列 的 in () 有异常
根据绑定变量的结构发现 selentity.total 为List<String> 集合 ,在集合元素为0 时产生如下异常
debug 代码发现异常出现在获取绑定参数的类中
@Override
public QueryParameters getQueryParameters() {
final QueryParameters queryParameters = super.getQueryParameters();
queryParameters.setCallable( callable );
queryParameters.setAutoDiscoverScalarTypes( autoDiscoverTypes );
if ( collectionKey != null ) {
queryParameters.setCollectionKeys( new Serializable[] {collectionKey} );
}
return queryParameters;
}
在 super.getQueryParameters() 方法中
public QueryParameters getQueryParameters() {
final String expandedQuery = getQueryParameterBindings().expandListValuedParameters( getQueryString(), getProducer() );
return makeQueryParametersForExecution( expandedQuery );
}
最终异常定位在 expandListValuedParameters 方法中
if ( ! dialect.supportsEmptyInList() && expansionListAsString.isEmpty() ) {
expansionListAsString = "null";
}
在绑定变量为集合的场景下,需要从方言中判断 在集合元素为0 的时候,拼接sql时 时候将空集合替换为null
在hibernate 默认的方言中配置为true ,即在空元素时 生成 in () sql语句,改为false 时 生成 in (null) 语法 ,在gbase 数据库中 不支持前者 ,导致 报错 201 语法错误
解决方案,需要重写方言中supportsEmptyInList() 方法,改为return false 即可