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
相关产品推荐
相关产品推荐

