Cassandra Repository @Query方法返回自定义类型报属性缺失错误如何解决?
问题解决方案
根因分析
你遇到的报错是因为UserRepository继承了CassandraRepository<User, String>,Spring Data Cassandra默认会将该Repository下所有自定义查询的结果,映射到泛型指定的主实体类User上,并不会自动识别你方法返回值声明的自定义DTOCountryAndNumUsers,因此会尝试在User类中查找numberOfUsers字段,找不到就抛出异常。
另外补充:你当前的CQL逻辑存在问题,group by id, country中id是表的主键,每行id唯一,分组后每一条的count结果都是1,无法实现按国家统计总用户数的需求。
可行解决方案
方案1:使用CassandraTemplate直接查询(最稳妥)
不在Repository中定义该方法,直接在业务层注入CassandraTemplate,手动指定结果映射的DTO类,代码示例:
import org.springframework.data.cassandra.core.CassandraTemplate; import org.springframework.jdbc.core.BeanPropertyRowMapper; // 业务类中注入 @Autowired private CassandraTemplate cassandraTemplate; public List<CountryAndNumUsers> getCountryUserCount() { // 调整CQL为按country分组,如需开启过滤请加ALLOW FILTERING(生产环境建议优化表结构适配查询) String cql = "Select country, count(*) as numberOfUsers from user group by country"; return cassandraTemplate.query(cql, new BeanPropertyRowMapper<>(CountryAndNumUsers.class)); }
方案2:使用接口投影(适合简单场景)
将自定义返回结果改为接口形式,Spring Data Cassandra会自动完成投影映射:
// 定义投影接口 public interface CountryAndNumUsersProjection { String getCountry(); Integer getNumberOfUsers(); }
调整Repository方法返回值:
public interface UserRepository extends CassandraRepository<User, String> { @Query("Select country, count(*) as numberOfUsers from user group by country") List<CountryAndNumUsersProjection> getListOfCountryAndNumUsers(); }
方案3:注册自定义结果映射
如果一定要用DTO类作为Repository方法返回值,可以自定义RowMapper并注册到Repository方法上:
// 自定义RowMapper public class CountryAndNumUsersMapper implements RowMapper<CountryAndNumUsers> { @Override public CountryAndNumUsers mapRow(Row row, int rowNum) throws DriverException { return new CountryAndNumUsers(row.getString("country"), (int) row.getLong("numberOfUsers")); } }
在Repository方法上指定映射器:
@Query(value = "Select country, count(*) as numberOfUsers from user group by country", rowMapperClass = CountryAndNumUsersMapper.class) List<CountryAndNumUsers> getListOfCountryAndNumUsers();
内容的提问来源于stack exchange,提问作者Njuacha Hubert
相关产品推荐
相关产品推荐

