本文主要研究一下如何使用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