Spring Data Cassandra按复合主键单个属性查询报错如何处理
问题原因及解决方案
1. 直接报错原因
你当前抛出No property userKeyUsername found for type User!的原因有两个:
- User实体类中复合主键的属性名为
key,不是userKey,和你方法名里写的前缀不匹配 - Spring Data Cassandra查询嵌套对象的属性时,需要用下划线
_分隔嵌套层级
修正后的Repository方法如下:
@Repository public interface UserRepo extends CassandraRepository<User, UserKey>{ User findByKey_Email(String email); User findByKey_Username(String username); }
2. 隐藏的查询规则问题
修正方法名后你仍无法正常完成查询,因为你当前的主键设计不符合Cassandra的查询规则:
你将id、username、email三个字段都设为了PARTITIONED类型的分区键,Cassandra要求查询时必须提供所有分区键作为过滤条件,才能定位到数据存储的节点,仅传入email或username单个条件是不允许的。
3. 实现单条件查询的可行方案
方案一:添加二级索引(适合低并发、小数据量场景)
给复合主键类中需要单独查询的字段添加@Indexed注解即可:
public class UserKey { @PrimaryKeyColumn(name = "id", ordinal = 0, type = PrimaryKeyType.PARTITIONED) private UUID id; @PrimaryKeyColumn(name = "username", ordinal = 1, type = PrimaryKeyType.PARTITIONED) @Indexed private String username; @PrimaryKeyColumn(name = "email", ordinal = 2, type = PrimaryKeyType.PARTITIONED) @Indexed private String email; // equals和hashcode方法 }
该方案改造量小,但Cassandra二级索引性能较低,不适合高并发查询场景。
方案二:冗余表设计(Cassandra官方推荐最佳实践,适合高并发、大数据量场景)
Cassandra是面向查询设计的数据库,针对每个查询模式单独建表是最优方案:
- 保留原有主表,用于需要同时传入三个主键的查询场景
- 新建
user_by_username表,主键仅为username,存储用户全量信息 - 新建
user_by_email表,主键仅为email,存储用户全量信息
写入数据时同步写入三张表,查询时根据入参选择对应表查询即可,性能远高于二级索引方案。
内容的提问来源于stack exchange,提问作者Zaid Sheikh
相关产品推荐
相关产品推荐

