gpt4 book ai didi

java - HQL:动态添加JOINS和WHERE部分(ANTLR,正则表达式或String)

转载 作者:塔克拉玛干 更新时间:2023-11-02 19:31:50 24 4
gpt4 key购买 nike

我必须编写基于HQL的引擎,该引擎会在运行中动态修补HQL查询,以动态添加联接和零件位置(以防止出现问题-我必须使用HQL,而不是标准API)。

例如。向HQL from Object a注入类似于from Object a JOIN a.path b WHERE b.id='XYZ'的东西

我看到了几种选择,但对我都不起作用:

  • Java String.insert()方法。查找WHERE语句的位置,并在该语句之前和之后添加连接。对于HQL来说,这不是一件微不足道的任务

    SELECT a,(从Object2 b选择WHERE b.path = a)从对象a存在(选择1 FROM ... WHERE)

  • 待处理算法:我可以计算每个WHERE之前的方括号()数量,如果它为零,则可以找到正确的WHERE位置。有人可以向我提出一种更简单的算法或Java上的简单实现吗?

    2.我怀疑我的任务可以通过正则表达式解决,但是不能为 String.replace()编写正确的正则表达式

    3.我看到了基于AST / ANTLR的语法,可以解析我的HQL,但是看不到如何对我有帮助的方法(即,我有声明,但是没有正确的声明 WHERE的位置)。

    4.存在用于SQL解析的独立库,但不适用于HQL。

    无论如何,感谢您的任何想法:)

    最佳答案

    以下是您提出的选项的一些想法。

    手动解析的

  • String.insert
    如果可以,则手动解析字符串可能是一种合理的方法,如果可以:a)轻松定义将要开始的HQL语法的子集,b)确信可以逐个字符地对其进行解析,并且c)知道子集语法很少或永远不会改变。听起来您必须遵循这样的方法:
  • 从流中读取一个字符。
  • 如果它是字符串的开头(例如'),请启动字符串读取方法,以便将'('')'不作为普通输入处理。如果它是字符串的结尾,请再次开始正常处理。
  • 如果它是分组表达式(例如'(')的开始,请开始跟踪新表达式,等等。
  • 如果是' ',请查看刚刚消耗的单词并决定如何处理它:如果它是表达式的开头(例如SELECT),请检查ID(例如a),然后检查下一个设置可能性并处理它们,依此类推。
  • 阅读下一个字符并重复步骤。

  • 通常,第一次添加听起来很难正确,如果添加或删除规则,则很难修改。我会避免使用这种方法来解决您的问题,但是如果您可以使输入像土一样简单,那么这是一个不错的解决方案。
  • 正则表达式

    这种方法比第一种更清洁,但是您将完全受限于正则表达式的局限性:您要分析的是结构化数据(SELECT a, (SELECT b ...) FROM Object a ...),而不是正则表达式最擅长的线性或平面数据。不过,如果将其与步骤1这样的手动过程结合使用,它可能会很好地工作……但这听起来也很困难。
  • 使用HQL语法的ANTLR

    标准的Hibernate下载包括ANTLR用于生成读取HQL的解析器的HQL语法文件。您可以将其与HQL / Hibernate代码分离(语法中有一些次要的依赖项),并将其缩减为您将要处理的内容。与前两个选项相比,这将为您带来两个很大的好处:从一开始,您将拥有一个功能完善的工作解析器,并且将对它进行编码以解析或多或少的官方HQL输入-很少“扎根”涉及编程。

    对于该选项,我可以考虑以下三个方面:HQL语法使用ANTLR 2.7版本,这在SO上似乎是众所周知的,但它是最新版本的一个(不久将是两个)版本。我不知道更新它是否很简单,但是根据我对ANTLR 3的经验以及对语法的了解,需要对这两个版本有所了解。但是,当然,您没有义务使用最新版本的ANTLR,因此,如果您希望成为最新版本,这只是一个缺点。

    第二个缺点是将语法与其他HQL代码分开的行为,这样您就不会使那些依赖项随处可见。您可能还想修剪掉不需要的规则,尽管这是一个微不足道的过程。对我来说,这里看起来没有什么困难,因为切掉无用/不可用的东西非常容易。

    第三个缺点是,您必须学习一些基本的ANTLR才能生成解析器代码并放心进行任何更改。我认为ANTLR的基础知识很容易学习,并且如果您需要的话,这里有很多支持,因此,与以前的缺点一样,我认为这很小。

    总的来说,我认为这种方法是一个很好的开始:您免费获得所需的语法,并且免费从该语法获得所需的解析器。所需要做的就是将语法与Hibernate项目和一些初学者的ANTLR知识分开。
  • 其他。独立的

    我想不出任何可以解决您的问题的项目。
  • ANTLR使用您自己的语法

    我添加了此选项作为选项3的替代方法。如果您知道开始的HQL子集并且对表示它的通用语法(不一定是ANTLR语法)很有信心,则可以从头开始编写自己的ANTLR语法,从中生成解析器。比起选择3,它的工作量更大,因为您会积累而不是精简,但是随着您对ANTLR的了解更多,您可能会更习惯于这种方法。

  • 对于一般的ANTLR解决方案,您可以通过分析(生成的)ANTLR解析器生成的AST树来找到放置 JOINWHERE子句的位置( this Bart Kiers answer显示了ANTLR解析器生成的简单树的示例)。如果您想讨论仅适用于ANTLR的解决方案,建议您提出一个新问题,以免与此处列出的其他选项纠缠不清。

    听起来您正在处理一个棘手的问题,我不知道所有细节,但是我认为在解决方案中使用ANTLR可以节省您的前期时间(无需编写手动分析器)以及将来的任何更改需要(只需更改语法并重新生成解析器)。我建议选择3或5,以适合您的舒适度。

    关于java - HQL:动态添加JOINS和WHERE部分(ANTLR,正则表达式或String),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12986782/

    24 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com