SpringBoot整合Cassandra时正确查询仍抛InvalidQueryException问题
我之前用SpringBoot结合Hibernate和Cassandra开发时,也碰到过一模一样的情况——之前基于ResultSet实现的方法全都运行正常,新增方法构造查询语句执行时突然就抛出了这个异常:
com.datastax.driver.core.exceptions.InvalidQueryException: No keyspace has been specified. USE a keyspace, or explicitly specify keyspace.tablename
你说查询语句直接在数据库客户端执行能返回正确结果,而且实现方式和之前正常的方法一致,先看看你给出的关键代码和查询语句:
构造查询的代码:
String queryString = query.toString().replace("?", dayList.toString()); ResultSet rS = dataSource.executeQuery(queryString);
可正常执行的查询语句:
SELECT * FROM object_action_statistics WHERE day IN ('2018-04-29','2018-04-30') AND action_id=14 AND timestamp_from>=1525099500073 AND timestamp_from<1525120897000 ALLOW FILTERING
其实问题出在Cassandra驱动的执行上下文上:你在数据库客户端执行时,应该已经通过USE keyspace_name切换到了目标keyspace,但通过Java驱动执行查询时,当前会话可能没有默认绑定keyspace;而之前正常的方法,大概率是通过Hibernate的实体映射自动带上了keyspace(比如实体类上标注了@Table(schema = "你的keyspace名称")),但这次构造的原生查询没处理好这一点。
给你几个可行的解决方案:
显式在查询语句中指定keyspace:把表名改成
keyspace名称.object_action_statistics,比如你的keyspace是app_stats,修改后的查询语句如下:SELECT * FROM app_stats.object_action_statistics WHERE day IN ('2018-04-29','2018-04-30') AND action_id=14 AND timestamp_from>=1525099500073 AND timestamp_from<1525120897000 ALLOW FILTERING这种方式最直接,不管当前会话有没有默认keyspace,都能准确定位到目标表。
配置数据源时指定默认keyspace:检查你的SpringBoot配置文件,给Cassandra数据源加上默认keyspace配置,比如在
application.properties中添加:spring.data.cassandra.keyspace-name=你的keyspace名称这样所有通过该数据源执行的查询都会默认使用这个keyspace,不用每次都手动写。
检查Query对象的构造逻辑:如果你是用Hibernate的Criteria或Query对象构造查询的,确认该对象是否正确关联了对应实体(实体类上已指定keyspace),避免构造出的SQL丢失keyspace信息。
你可以先试试第一种方法,直接修改查询语句加上keyspace,应该能快速验证问题是否解决。
内容的提问来源于stack exchange,提问作者Bob

