jirutka / rsql-parser和QueryDSL

时间:2014-10-21 16:43:39

标签: java spring parsing spring-data querydsl

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

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

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

我对它以及QueryDsl都很陌生。

现在我很困惑,所以这是我的求助请求:
是否有人在休息弹簧项目中集成了 jirutka / rsql-parser QueryDsl 如何?

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,我需要知道I类处理,例如:

    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,因为我需要首先通过一些ComparisonNode方法,然后将它们加入&#34;或&#34;或&#34;和&#34;布尔表达式。正确?

如果至少我可以通过所有节点,那么我可以设法找到通过课程的方法,我并不担心。但是不了解如何遍历所有节点,并且无法做到这一点。

任何解决这个问题的指示都将非常感激。

1 个答案:

答案 0 :(得分:0)

一如既往,在提出问题后(我认为)取得了很大进展。

找到一种遍历所有节点的方法,并找到了将QueryDsl PathBuilder<?>对象传递给访问者的方法。

PathBuilder<?>是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);
        }

    }

}