Spring Data Cassandra无法直接通过复合主键查询数据问题
解决Spring Data Cassandra复合主键查询的QueryCreationException问题
嘿,我太懂这个坑了!你遇到的这个QueryCreationException核心原因就是Spring Data Cassandra不允许直接把整个复合主键类作为查询参数,必须明确引用主键类里的具体属性才行——异常提示里已经把原因说得明明白白:Cannot use composite primary key directly. Reference a property of the composite primary key。
给你两种靠谱的解决方案,结合你的代码场景来调整:
方案1:使用Spring Data命名查询规则(推荐)
首先确认你的复合主键类(带@PrimaryKeyClass注解的Key类)的结构,比如假设它是这样的:
@PrimaryKeyClass public class Key implements Serializable { @PrimaryKeyColumn(name = "service_id", ordinal = 0, type = PrimaryKeyType.PARTITIONED) private String serviceId; @PrimaryKeyColumn(name = "version", ordinal = 1, type = PrimaryKeyType.CLUSTERED) private Integer version; // 记得实现构造器、getter、setter,以及正确重写equals()和hashCode()方法 }
然后修改你的ServiceRepository接口,把原有的findByKey(Key key)方法,改成引用主键类里的具体属性:
public interface ServiceRepository extends CassandraRepository<ServiceEntity, Key> { // 按完整复合主键查询(等价于传整个Key对象的效果) List<ServiceEntity> findByKeyServiceIdAndKeyVersion(String serviceId, Integer version); // 如果只需要按分区键查询(比如查询某个serviceId下的所有版本数据) List<ServiceEntity> findByKeyServiceId(String serviceId); }
这里的命名规则是:用实体类中复合主键字段的名称(比如key)作为前缀,后面跟上主键类里的属性名,多个属性用And连接,Spring Data会自动解析成对应的CQL查询。
方案2:用@Query注解自定义查询(保留原方法签名)
如果你想保留findByKey(Key key)这个方法签名,不想拆分参数,可以用@Query注解直接写CQL语句:
public interface ServiceRepository extends CassandraRepository<ServiceEntity, Key> { @Query("SELECT * FROM service WHERE service_id = ?0.serviceId AND version = ?0.version") List<ServiceEntity> findByKey(Key key); }
这里的?0代表方法的第一个参数(也就是你的Key对象),直接引用它的属性serviceId和version即可,Cassandra会正确解析这个参数。
额外注意点
- 复合主键类必须实现
Serializable接口,并且正确重写equals()和hashCode()方法,这是Spring Data Cassandra对主键类的强制要求。 - 命名查询的属性名要和实体类、主键类的getter方法对应,避免因名称不匹配导致解析失败。
内容的提问来源于stack exchange,提问作者Gekster
相关产品推荐
相关产品推荐

