代码之家  ›  专栏  ›  技术社区  ›  aberrant80

保存hql或ejb ql的数据结构

  •  1
  • aberrant80  · 技术社区  · 15 年前

    我们需要生成一个相当复杂的动态查询生成器来实时检索报告。我们对什么样的数据结构才是最好的有点摸不着头脑。

    它实际上只不过是保存一个选择部分的列表,一个来自部分的列表,一个位置标准的列表,排序依据,分组依据,诸如此类的东西,用于持久性。当我们开始考虑连接时,特别是外部连接、有子句和聚合函数,事情开始变得有点模糊。

    我们现在首先构建接口,并尽可能地向前思考,但当我们发现结构的局限性时,肯定会经历一系列重构。

    我把这个问题贴在这里,希望有人已经提出了一些可以作为基础的问题。或者知道一些图书馆之类的。在我们下周深入研究实现之前,最好能得到一些提示或是对潜在问题的注意。

    2 回复  |  直到 13 年前
        1
  •  2
  •   Mike Q    15 年前

    我以前也做过类似的事情。一些更大的事情浮现在脑海中……

    • WHERE子句最难纠正。如果你把事情分成我称之为“表达式”和“谓词”的部分,会更容易些。
    • 表达式-列引用、参数、文本、函数、聚合(计数/求和)
    • 谓词-比较,如,between,in,为空(谓词将表达式作为子级,例如expr1=expr2)。然后你也有复合材料,比如和/或/或/不。
    • 可以想象,整个WHERE子句是一棵树,根上有一个谓词,下面可能有子谓词,最后以叶上的表达式结束。
    • 要构造HQL,您需要遍历模型(通常是深度优先)。由于其他原因,我使用了一个访问者,因为我需要浏览我的模型,但是如果您没有多个目的,那么您可以直接在模型中构建呈现代码。

    如果你有

    "where upper(column1) = :param1 AND ( column2 is null OR column3 between :param2 and param3)"
    

    那么这棵树就是

    Root
    - AND
      - Equal
        - Function(upper)
          - ColumnReference(column1)
        - Parameter(param1)
      - OR
        - IsNull
          - ColumnReference(column2)
        - Between
          - ColumnReference(column3)
          - Parameter(param2)
          - Parameter(param3)
    

    然后,首先遍历树的深度,然后在返回的过程中合并HQL的渲染位。例如,upper函数将期望呈现一个子HQL,然后它将生成

    "upper( " + childHql + " )"

    把它传给它的父母。像between这样的东西需要三个child-hql片段。

    • 然后可以在select/group by/order by子句中重新使用表达式模型。

    • 如果愿意,可以跳过存储group by,方法是只存储select,然后在查询结构扫描聚合之前。如果有一个或多个,则只需将所有非聚合select表达式复制到group by中即可。

    • FROM子句只是表引用+零个或多个联接子句的列表。每个join子句都有一个类型(inner/left/right)和一个表引用。表引用是表名+可选别名。

    另外,如果你想要解析一种查询语言(或者其他真正的语言),那么我强烈推荐你 ANTLR . 学习曲线相当陡峭,但有很多示例语法值得一看。

    Hth.

        2
  •  0
  •   animuson Hemanshu    13 年前

    如果您需要EJB-QL解析器和数据结构,EclipseLink(它的几个内部类)有一个很好的:

    JPQLParseTree tree = org.eclipse.persistence.internal.jpa.parsing.jpql.JPQLParser.buildParserFor(" _the_ejb_ql_string_ ").parse();
    

    JPQLParseTree 包含所有数据。

    但从修改后的 JPQLPARSETRE 是你必须自己做的事。

    推荐文章