序
本文主要研究一下如何使用RSQL實(shí)現(xiàn)從前端到后端的動(dòng)態(tài)數(shù)據(jù)查詢。
RSQL
RSQL(RESTful Service Query Language)是Feed Item Query Language (FIQL) 的超集,是一種RESTful服務(wù)的查詢語(yǔ)言。這里我們使用rsql-jpa來(lái)實(shí)踐,它依賴rsql-parser來(lái)解析RSQL語(yǔ)法,然后將解析后的RSQL轉(zhuǎn)義到JPA的Specification。
maven
<dependency>
<groupId>com.github.tennaito</groupId>
<artifactId>rsql-jpa</artifactId>
<version>2.0.2</version>
</dependency>
它依賴了rsql-parser
實(shí)例
domain
@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;
//...
}
controller
@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));
}
}
service
@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來(lái)查詢,總共分三步,1是創(chuàng)建RSQLVisitor,2是解析condition到Node,3是根據(jù)node創(chuàng)建CriteriaQuery,然后就可以根據(jù)CriteriaQuery來(lái)查詢了。
運(yùn)行
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轉(zhuǎn)義,如果有多個(gè)and條件,用;分隔
小結(jié)
RSQL是一種強(qiáng)大抽象的語(yǔ)言,可以用來(lái)做REST服務(wù)的通用查詢語(yǔ)言,spring-data-rest也提供了類(lèi)似的功能,功能更為強(qiáng)大。不過(guò)這種貌似不支持or查詢,另外數(shù)據(jù)量大的時(shí)候,直接走db查詢可能造成慢查詢,因?yàn)椴⒉皇撬凶侄味加兴饕贿^(guò)對(duì)于走elasticsearch來(lái)說(shuō),還是比較合適的。