本文主要研究一下如何使用RSQL实现从前端到后端的动态数据查询。html
RSQL(RESTful Service Query Language
)是Feed Item Query Language (FIQL) 的超集,是一种RESTful服务的查询语言。这里咱们使用rsql-jpa来实践,它依赖rsql-parser来解析RSQL语法,而后将解析后的RSQL转义到JPA的Specification。前端
<dependency> <groupId>com.github.tennaito</groupId> <artifactId>rsql-jpa</artifactId> <version>2.0.2</version> </dependency>
它依赖了rsql-parser
@Entity public class TodoTask { @javax.persistence.Id @GeneratedValue(strategy = GenerationType.AUTO) private Long id; private Long totalNum = 0L; private String title; @Version private Long version; //... }
@RestController @RequestMapping("/rsql") public class RsqlController { @Autowired TodoTaskService todoTaskService; /** * @param condition * @param page * @param size * @return */ @GetMapping("") public Page<TodoTask> query(@RequestParam String condition, @RequestParam(required = false,defaultValue = "0") int page, @RequestParam(required = false,defaultValue = "20") int size){ return todoTaskService.query(condition,new PageRequest(page,size)); } }
@Component public class TodoTaskService { @Autowired private EntityManager entityManager; public Page<TodoTask> query(String condition, Pageable pageable){ // 1.Create the JPA Visitor RSQLVisitor<CriteriaQuery<TodoTask>, EntityManager> visitor = new JpaCriteriaQueryVisitor<TodoTask>(); // 2.Parse a RSQL into a Node Node rootNode = new RSQLParser().parse(condition); // 3.Create CriteriaQuery CriteriaQuery<TodoTask> criteriaQuery = rootNode.accept(visitor, entityManager); List<TodoTask> total = entityManager.createQuery(criteriaQuery).getResultList(); List<TodoTask> resultList = entityManager.createQuery(criteriaQuery) .setFirstResult(pageable.getOffset()).setMaxResults(pageable.getPageSize()).getResultList(); return new PageImpl<>(resultList,pageable, total.size()); } }
这里直接使用EntityManager来查询,总共分三步,1是建立RSQLVisitor,2是解析condition到Node,3是根据node建立CriteriaQuery,而后就能够根据CriteriaQuery来查询了。
curl -i http://localhost:8080/rsql?condition=title==hello curl -i http://localhost:8080/rsql?condition=totalNum%3E50 curl -i http://localhost:8080/rsql?condition=totalNum%3E50;title==hello
其中%3E是>的url转义,若是有多个and条件,用;分隔
RSQL是一种强大抽象的语言,能够用来作REST服务的通用查询语言,spring-data-rest也提供了相似的功能,功能更为强大。不过这种貌似不支持or查询,另外数据量大的时候,直接走db查询可能形成慢查询,由于并非全部字段都有索引,不过对于走elasticsearch来讲,仍是比较合适的。java