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

DataStax Cassandra驱动4.15.0下CQL IN子句绑定列表报错咨询

问题描述

使用DataStax Cassandra 4.15.0版本驱动(依赖配置如下):

<dependency>
    <groupId>com.datastax.oss</groupId>
    <artifactId>java-driver-bom</artifactId>
    <version>4.15.0</version>
    <type>pom</type>
    <scope>import</scope>
</dependency>

执行删除语句代码时:

...
List<String> myList= new ArrayList<>();
myList.add("+4911111111");

final BoundStatement bs = prepareAndBind(cqlSession, "delete "
        + "from test.numbers "
        + "where id=:customerId "
        + "and phonenumbers in (:phoneNumbers) ")
        .setLong("customerId", customerId)               
        .setList("phoneNumbers", myList, String.class)
...

抛出如下异常:

com.datastax.oss.driver.api.core.type.codec.CodecNotFoundException: Codec not found 
for requested operation: [TEXT <-> java.util.List<java.lang.String>]

该代码在旧版本驱动中可正常运行,请问当前驱动版本下,创建带WHERE IN ()子句的语句的最佳方式是什么?是否需要自定义codec,还是有更简便的方法?

解决方案

问题根源是4.x版本驱动对IN子句的参数绑定逻辑做了调整:旧版本允许用集合绑定IN参数,但4.x版本中IN期望接收的是多个独立的单个值,而非集合类型,所以用setList会触发Codec不匹配的异常。

无需自定义Codec,以下是两种简便的原生解决方案:

方法一:直接绑定集合参数

4.x版本驱动已支持直接将集合绑定到IN的命名参数,替换setList为普通的set方法即可:

final BoundStatement bs = prepareAndBind(cqlSession, "delete "
        + "from test.numbers "
        + "where id=:customerId "
        + "and phonenumbers in (:phoneNumbers) ")
        .setLong("customerId", customerId)               
        .set("phoneNumbers", myList);

也可以将集合转为数组传入:

final BoundStatement bs = prepareAndBind(cqlSession, "delete "
        + "from test.numbers "
        + "where id=:customerId "
        + "and phonenumbers in (:phoneNumbers) ")
        .setLong("customerId", customerId)               
        .set("phoneNumbers", myList.toArray(new String[0]));

方法二:动态生成占位符(适用于元素数量不固定场景)

如果列表长度动态变化,可以先生成对应数量的占位符,再绑定参数:

// 根据列表长度生成占位符,如1个元素生成"?",多个生成"?,?"
String placeholders = String.join(",", Collections.nCopies(myList.size(), "?"));
String cql = String.format("delete from test.numbers where id=? and phonenumbers in (%s)", placeholders);

final BoundStatement bs = cqlSession.prepare(cql)
        .bind(customerId, myList.toArray());

优先推荐方法一,代码更简洁且符合驱动4.x的设计规范。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.29 12:57:09