我目前正在使用面向微服务架构的项目。我正在使用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存储库,即使我们不知道我们的服务收到了什么查询?
答案 0 :(得分:2)
有很多方法可以解决这个问题,但一种简单的方法是使用自定义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
仅支持匹配值。