如何使用 Spring Data Redis 存储库构建动态查询?

How to build dynamic queries with Spring Data Redis Repositories?

我正在使用 spring-data-redis 使用这样的存储库测试 Redis:

public interface CreditCardRepository extends CrudRepository<CreditCard, String>{
    List<CreditCard> findByIssuer(String issuer);
    List<CreditCard> findByCreditNetwork(String creditNetwork);
    List<CreditCard> findByCreditNetworkAndIssuer(String creditNetwork, String issuer);
}

以上方法将查询像这样的 Redis 结构:

creditcard:creditNetwork:mastercard
creditcard:creditNetwork:visa
creditcard:issuer:company1
creditcard:issuer:company2

现在我的 CreditCard 对象包含两个属性(issuer、network 和 id),所以很容易搜索这样的对象:

private List<CreditCard> searchCardFromCache(CreditCardGetReq req) {
    if (req.getIssuer() != null && req.getNetwork() != null) { 
        return ccRepository.findByIssuerAndCreditNetwork(req.getIssuer(), req.getNetwork().name()); 
    }
    if (req.getIssuer() != null) { 
        return ccRepository.findByIssuer(req.getIssuer()); 
    }
    if (req.getNetwork() != null) { 
        return ccRepository.findByCreditNetwork(req.getNetwork().name()); 
    }
    return null;
}

但是,我不喜欢这段代码,因为我必须创建所有属性的组合并且会非常混乱。将来我打算有 15 个属性,所以 'if' 链是不可能的。

我想问你如何使用 spring-data-redis 创建动态查询,这样 Redis 可以 return 基于对象属性的交集比检查每个更好的方式属性?

已尝试通过硬编码使用 MethodHandle(我之前从存储库中删除 findByIssuerAndCreditNetwork)方法名称将动态生成,如下所示:

MethodType methodType = MethodType.methodType(cardList.getClass(), String.class, String.class);
// Dynamic create 'findByIssuerAndCreditNetwork'
MethodHandle methodHandle = MethodHandles.lookup().findVirtual(CreditCardRepository.class, "findByIssuerAndCreditNetwork", methodType);

但似乎 MethodHandle 不起作用,因为我遇到以下错误:

java.lang.NoSuchMethodException: no such method: com.creditcard.dao.CreditCardRepository.findByIssuerAndCreditNetwork(String,String)ArrayList/invokeInterface

目前不支持创建动态查询。听起来好像 Query by Example 可能就是您要找的东西。 Spring Data MongoDB 和 Spring Data JPA 已经实现了 Query by Example。

数据存储模块创建查询以匹配示例域对象:

Person person = new Person();                         
person.setFirstname("Dave");                          

Example<Person> example = Example.of(person); 

MongoRepository repo = …
List<Person> result = repo.findAll(example); // returns all objects that with Dave in firstname

Spring Data Redis 目前不支持示例查询,但应该可以提供基本支持。

我创建了一个工单 DATAREDIS-605 来跟踪此功能的进度。