1

我们需要生成一个相当复杂的动态查询构建器来动态检索报告。对于哪种数据结构最好,我们有点摸不着头脑。

它实际上只不过是持有一个 selectParts 列表、一个 fromParts 列表、一个 where 标准列表、order by、group by 之类的东西,用于持久性。当我们开始考虑连接,尤其是外连接、有子句和聚合函数时,事情开始变得有点模糊。

我们现在首先构建它的接口并尝试尽可能远地思考,但是当我们发现我们的结构存在限制时肯定会经历一系列重构。

我在这里发布这个问题是希望有人已经提出了一些我们可以作为基础的东西。或者知道一些图书馆或类似的图书馆。在我们下周深入实施之前,最好能获得一些关于潜在问题的提示或提示。

4

2 回答 2

2

我过去做过几次类似的事情。一些更大的事情浮现在脑海中。

  • where 子句是最难搞定的。如果你把事情分成我所说的“表达式”和“谓词”,它会更容易。
  • 表达式 - 列引用、参数、文字、函数、聚合(计数/总和)
  • 谓词 - 比较,如,之间,在,为空(谓词有表达式作为子项,例如 expr1 = expr2。然后你也有复合词,如和/或/不。
  • 可以想象,整个 where 子句是一棵树,其根部有一个谓词,下面可能还有子谓词,最终在叶子处以表达式结束。
  • 要构建 HQL,您需要遍历模型(通常是深度优先)。我使用了一个访问者,因为我出于其他原因需要走我的模型,但如果您没有多种用途,您可以将渲染代码直接构建到模型中。

例如,如果你有

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

然后树是

根
- 和
  - 平等的
    - 功能(上)
      - 列参考(column1)
    - 参数(param1)
  - 或者
    - 一片空白
      - 列参考(column2)
    - 之间
      - 列参考(column3)
      - 参数(param2)
      - 参数(param3)

然后,您首先遍历树深度,并在返回的路上合并 HQL 的渲染位。例如,上层函数会期望渲染一段子 HQL,然后生成

"upper( " + childHql + " )"

并将其传递给它的父母。像 Between 这样的东西需要三个子 HQL 片段。

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

  • 如果您愿意,您可以通过仅存储选择和查询构造扫描之前的聚合来跳过存储组。如果有一个或多个,则只需将所有非聚合选择表达式复制到 group by。

  • From 子句只是表引用 + 零个或多个连接子句的列表。每个连接子句都有一个类型(内/左/右)和一个表引用。表引用是表名 + 可选别名。

另外,如果您想要解析查询语言(或其他任何东西),那么我强烈推荐ANTLR。学习曲线非常陡峭,但有很多示例语法可供查看。

HTH。

于 2009-10-16T10:43:16.963 回答
0

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

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

JPQLParseTree包含所有数据。

但是从修改后生成 EJB-QLJPQLParseTree是您必须自己做的事情。

于 2010-06-01T13:44:14.267 回答