springboot data jpa 适配 gbase8s 报错could not prepare statement

在适配过程中,发现部分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 即可

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值