jirutka/rsql-parser 和 QueryDSL

Posted

技术标签:

【中文标题】jirutka/rsql-parser 和 QueryDSL【英文标题】:jirutka/rsql-parser and QueryDSL 【发布时间】:2014-12-16 23:39:24 【问题描述】:

我有 Spring 框架创建了后端的 REST 服务,现在我需要找到一种方法来处理来自前端的一些请求中的复杂过滤器。

我正在使用 QueryDsl (v3.4.2) 框架在整个后端进行查询构建。

我认为使用 FIQL 或 RSQL 解析器是最好的方法,因此我正在尝试将 jirutka/rsql-parser 集成到我的后端项目中。

我对它很陌生,对 QueryDsl 也很陌生。

现在我很困惑,所以这里是我的帮助请求:有没有人在休息春天集成 jirutka/rsql-parserQueryDsl之前的项目?如何?

Jirutka/rsql-parser 文档只说:

节点是可访问的,因此要遍历解析的 AST(并将其转换为 SQL查询可能),您可以实现提供的RSQLVisitor接口 或简化的 NoArgRSQLVisitorAdapter。

并有以下示例说明如何做到这一点:

Node rootNode = new RSQLParser().parse("name==RSQL;version=ge=2.0");
rootNode.accept(yourShinyVisitor);

看起来很简单,对吧?

所以我把我的访问者这样装箱:

public class RsqlParserVisitor extends NoArgRSQLVisitorAdapter<BooleanExpression> 

实现了接口要求我执行的所有方法。

这里我补充两个例子:

@Override
public BooleanExpression visit(AndNode arg0) 
    // TODO Auto-generated method stub

    String methodNameTmp = "AndNode";
    logger.debug(methodNameTmp + ". arg0: " + arg0);
    logger.debug("operator: " + arg0.getOperator().name());
    for (Node node : arg0) 
        logger.debug(methodNameTmpp + ". node: " + node);
    

    return null; //DO SOMETHING TO CREATE A BooleanExpression;

@Override
public BooleanExpression visit(EqualNode arg0) 
    // TODO Auto-generated method stub
    String methodNameTmp = "EqualNode";
    logger.debug(methodNameTmp + ". arg0: " + arg0);

    logger.debug("operator: " + arg0.getOperator());
    for (String arg: arg0.getArguments()) 
        logger.debug(methodNameTmp + ". arg: " + arg);
    

    return null; //DO SOMETHING TO CREATE A BooleanExpression;

现在我被困住了:

a) 为了创建 QueryDsl BooleanExpression,我需要知道我正在处理的类,例如:

    QUser qUser = QUser.user;
    BooleanExpression filter = qUser.firstName.eq("Bob");

    PathBuilder<User> user = new PathBuilder<User>(User.class, "user");
    BooleanExpression filter = user.getString("firstName").eq("Bob");

b) 当我测试我的代码时,它只执行public BooleanExpression visit(OrNode arg0) 方法,然后什么也不执行。它就停在那里。

那一刻我无能为力。还不能创建 BooleanExpression,因为我需要先通过一些比较节点方法,然后将它们与“或”或“和”布尔表达式连接起来。对吧?

如果至少我可以通过所有节点,那么我可以设法找到通过类的方法,我不担心。但是不明白怎么遍历所有节点,一直没能做到。

任何解决此问题的指针,将不胜感激。

【问题讨论】:

您有没有找到完整的解决方案?我很想听听。 我最终自己动手了......到目前为止一切都很好:它正在工作。但是我时不时地需要在不工作的时候修复一些东西;我知道这并不完美。如果您有具体问题,我很乐意提供帮助。我希望很快我能找到一些空闲时间(哈哈)并且可以在这里提出一些建议,但不能承诺任何事情。 :) 【参考方案1】:

与往常一样,在提出问题后取得了很大的(我认为)进展。

找到了遍历所有节点的方法,找到了将QueryDsl PathBuilder&lt;?&gt;对象传递给访问者的方法。

PathBuilder&lt;?&gt; 是 QueryDsl 创建的所有 QSomething 类的父类。

现在我再次陷入寻找创建 BooleanExpression 的方法。

任何帮助将不胜感激。

我的服务中现在有以下内容:

@Override
public Page<User> getUsers(Emisor pEmisor, int pPage, int pSize, Sort pSort, String pRSQLFilters) 

    Pageable pageable = new PageRequest(pPage, pSize, pSort);

    BooleanExpression filters = null;

    Node queryTree;
    try 
        logger.debug("Parsing query: ", pRSQLFilters);
        queryTree = new RSQLParser().parse(pRSQLFilters);

        RsqlParserVisitor<BooleanExpression, QUser> rsqlParserVisitor = new RsqlParserVisitor<BooleanExpression, QUser>();
        filters = queryTree.accept(rsqlParserVisitor, QUser.user);

     catch (TokenMgrError e) 
        // TODO Auto-generated catch block
        e.printStackTrace();
     catch (RSQLParserException e) 
        // TODO Auto-generated catch block
        e.printStackTrace();
    


    Page<User> lista  = userRepository.findAll(filtros, pageable);

    return lista;

    

这在访问者中:

public class RsqlParserVisitor<BooleanExpression, A> implements RSQLVisitor<BooleanExpression, EntityPathBase<?>> 
...
    @Override
    public BooleanExpression visit(OrNode node, EntityPathBase<?> param) 
        // TODO Auto-generated method stub

        String nombreTmp = "OrNode";
        printLogicalNode(nombreTmp, node, param);

        return null;
    

    @Override
    public BooleanExpression visit(EqualNode node, EntityPathBase<?> param) 
        // TODO Auto-generated method stub

        String nombreTmp = "EqualNode";
        printComparisonNode(nombreTmp, node, param);

        return null;
    

...

    public void printLogicalNode(String pNombreNodo, LogicalNode pNode,
            EntityPathBase<?> pParam) 
        logger.debug(pNombreNodo + ". node: " + pNode + ". param: " + pParam);

        logger.debug("operator: " + pNode.getOperator().name());

        for (Node subNode : pNode) 
            logger.debug(pNombreNodo + ". subNode: " + subNode);
            subNode.accept(this, pParam);    <=========== this was the key to be able to traverse every node
        
    

    public void printComparisonNode(String pNombreNodo, ComparisonNode pNode,
            EntityPathBase<?> pParam) 
        logger.debug(pNombreNodo + ". node: " + pNode + ". param: " + pParam);

        logger.debug("Selector: " + pNode.getSelector());
        logger.debug("operator: " + pNode.getOperator());

        for (String argTmp : pNode.getArguments()) 
            logger.debug(pNombreNodo + ". argTmp: " + argTmp);
        

    


【讨论】:

嗨,我有一个简单的开源项目,它结合了 rsql-parser v2.x.x 和 querydsl-core v3.x.x,它仍在进行中。我从结合 rsql-parser v1.x.x 和 querydsl 的工作经验中得出它。这次想把它暴露在github上,你可以在这里找到。 github.com/vineey/rsql-querydsl目前,我正在这个分支上工作github.com/vineey/rsql-querydsl/tree/feature/filter-api 仅供参考,我计划在 2015 年 10 月或之前完成这个库。 仅供参考,我很高兴地宣布我的开源项目 rsql-queryds 的第一个生产版本标记为 1.0.0.RELEASE github.com/vineey/archelix-rsql 太棒了。我希望我能尽快看看

以上是关于jirutka/rsql-parser 和 QueryDSL的主要内容,如果未能解决你的问题,请参考以下文章

等待队列_睡眠和唤醒

interview que

Leetcode 117

Gym101138D Strange Queries 莫队前缀和容斥

sql Seeliminalimitaciónamostrarsólo16registros ya que ocasionaba que no se mostrara todas

queue模块的使用