如果我正在使用 RestFul 服务,我该如何利用 Spring 存储库?

How can I take advantage of Spring repositories if I am using RestFul Services?

我目前正在从事一个使用面向微服务架构的项目。我正在使用 Spring boot + MongoDB 存储库,因此我们的团队可以通过不必编写查询来节省一些时间。

我们在使用这种方法时遇到了问题。如果我们有实体用户:

{
"name":"Josh",
"lastname":"Smith"
"createdOn":"2018-01-01 00:00:00"
} 

我们想将这个实体公开为资源,但我们真的不知道客户端将使用什么参数来搜索这个存储库,所以我们最终会得到类似的东西:

    @GetMapping
    public ResponseEntity<User>get(@RequestParam(value = "name") String name,
    @RequestParam(value = "name") String lastname){...}

还有一个存储库:

public List<User> findByName(String name); public List<User> findByLastName(String lastname); ...

我们将不得不在用户存储库和条件中创建很多方法,以使用它们根据客户的查询给出答案。随着实体获得更多字段,这个问题会越来越严重。

我知道 spring 支持 query by example 但如果我们需要按日期范围搜索,它就不起作用了。

有没有一种方法可以利用 Spring 存储库,即使我们不知道我们的服务接收到哪些查询?

有很多方法可以解决这个问题,但一种简单的方法是使用自定义 QueryDTO 和所有查询属性,如下所示。

public class QueryDTO {
    private String firstName;
    private String lastName;

    // Getters and Setters
}

并且在您的存储库中,您可以扩展 QueryByExampleExecutor

public interface UserRepository extends CrudRepository<User, Long>, QueryByExampleExecutor<User> {...}

并且您的控制器方法应执行以下操作;

@Autowired
private UserRepository userRepository;

@GetMapping
public ResponseEntity<User> get(@RequestParam(value = "q") String query) {
    QueryDTO queryDto = new ObjectMapper().readValue(query, QueryDTO.class);

    // You can write a converter to convert QueryDTO to User Example  
    User user = new User();
    user.setFirstName(queryDto.getFirstName());
    user.setLastName(queryDto.getLastName());
    Example<User> example = Example.of(user);

    return new ResponseEntity<User>(userRepository.findOne(example), HttpStatus.OK);
}

现在,无论您有多少新字段都可以修改 QueryDTO 以添加新字段并启用按这些字段进行搜索。

更新

如果您需要按范围或使用自定义值进行查询,您可以在 UserRepository 中扩展 QueryDslPredicateExecutor。但是顾名思义QueryByExampleExecutor只支持匹配值