用于保存HQL或EJB QL的数据结构

时间:2009-10-16 09:57:28

标签: data-structures hql ejbql

我们需要生成一个相当复杂的动态查询构建器,以便即时检索报告。我们对于什么样的数据结构最好是我们的头脑。

它实际上只不过是包含一个selectParts列表,一个fromParts列表,一个列表,其中包含标准,order by,group by,that that that for persistence。当我们开始考虑连接,特别是外连接,有子句和聚合函数时,事情开始变得有些模糊。

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

我在这里发布这个问题,希望有人已经想出了一些我们可以依据的东西。或者知道一些图书馆或其他一些。在我们下周深入实施之前,最好先获得一些潜在问题的提示或提示。

2 个答案:

答案 0 :(得分:2)

我过去做过几次类似的事情。我想到了一些更大的事情......

  • where子句是最难做到的。如果你把事情分成我称之为“表达式”和“谓词”的东西,那就更容易了。
  • 表达式 - 列引用,参数,文字,函数,聚合(计数/总和)
  • 谓词 - 比较,例如,在,之间,是null(谓词表达式为子项,例如expr1 = expr2。然后你还有复合词,如和/或/不。
  • 你可以想象,整个where子句是一个在根上有谓词的树,下面可能有子谓词,最后用叶子上的表达式终止。
  • 要构建HQL,您需要遍历模型(通常是深度)。我使用访问者因为其他原因需要走模型,但如果没有多个用途,可以将渲染代码直接构建到模型中。

e.g。如果你有

"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位。例如,上层函数会期望渲染一个子HQL,然后生成

"upper( " + childHql + " )"

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

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

  • 如果您希望通过仅存储select和查询构造扫描以进行聚合,则可以跳过存储组。如果有一个或多个,则只需将所有非聚合选择表达式复制到组中。

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

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

HTH。

答案 1 :(得分:0)

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

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

JPQLParseTree包含所有数据。

但是从修改后的JPQLParseTree生成EJB-QL是你必须自己做的事情。