如果我正在使用 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
只支持匹配值
我目前正在从事一个使用面向微服务架构的项目。我正在使用 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
只支持匹配值