序
本文主要研究一下如何使用RSQL实现从前端到后端的动态数据查询。
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来说,还是比较合适的。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。