[case10]使用RSQL實現端到端的動態查詢

本文主要研究一下如何使用RSQL實現從前端到後端的動態數據查詢。html

RSQL

RSQL(RESTful Service Query Language)是Feed Item Query Language (FIQL) 的超集,是一種RESTful服務的查詢語言。這裏咱們使用rsql-jpa來實踐,它依賴rsql-parser來解析RSQL語法,而後將解析後的RSQL轉義到JPA的Specification。前端

maven

<dependency>
    <groupId>com.github.tennaito</groupId>
    <artifactId>rsql-jpa</artifactId>
    <version>2.0.2</version>
</dependency>
它依賴了rsql-parser

實例

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來查詢,總共分三步,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

doc

相關文章
相關標籤/搜索