【问题标题】:Hibernate: Parse/Translate HQL FROM part to get pairs class alias, class nameHibernate:解析/翻译 HQL FROM 部分以获取对类别名、类名
【发布时间】:2010-09-24 08:35:43
【问题描述】:

谁能指出我,我如何解析/评估 HQL 并获取键是表别名和值的映射 - 完全限定的类名。

例如对于 HQL

SELECT a.id from Foo a INNER JOIN a.test b

我希望有一对:

a,package1.Foo

b. package2.TestClassName

结果集比较容易做

HQLQueryPlan hqlPlan = ((SessionFactoryImpl)sf).getQueryPlanCache().getHQLQueryPlan( getQueryString(), false, ((SessionImpl)session).getEnabledFilters() );
String[] aliases = hqlPlan.getReturnMetadata().getReturnAliases();
Type[] types = hqlPlan.getReturnMetadata().getReturnTypes();

details here

【问题讨论】:

    标签: java hibernate hql


    【解决方案1】:

    这不是一个好方法,但似乎您可以通过一些内部接口获取 AST 并遍历它:

    QueryTranslator[] translators = hqlPlan.getTranslators();
    AST ast = (AST)((QueryTranslatorImpl)translators[0]).getSqlAST();
        new NodeTraverser(new NodeTraverser.VisitationStrategy() {
        public void visit(AST node) {
            if(node.getType() == SqlTokenTypes.FROM_FRAGMENT || node.getType() == SqlTokenTypes.JOIN_FRAGMENT) {
                FromElement id = (FromElement)node;
                System.out.println(node+": "+id.getClassAlias()+" - "+id.getClassName());
            }
        }
    }).traverseDepthFirst(ast);
    

    所以这似乎是从编译的查询中检索别名映射,但我会非常小心地使用这个解决方案:它将对象类型转换为通常对休眠客户端不可见的子类,并根据猜测的语义解释 AST不同的节点。这可能不适用于所有 HQL 语句,并且可能不适用于未来的休眠版本,或者具有不同的行为。

    【讨论】:

    • 我根据我们的内部 API(条件窗格等)动态生成 HQL,并且对于过滤条件(即 WHERE 部分)需要知道 HQL 中每个类的别名。
    • 看起来 SqlTokenTypes.ALIAS_REF 不是我想要的。在我上面的示例中,结果将是“a,package1.Foo”,但我也需要“b,package2.TestClassName”。我的意思是 ALIAS_REF 处理“SELECT”部分而不是“FROM”。
    • 关于您使用 Criteria API 的问题。我有两个原因: 1. 遗留代码 2. HQL 允许您构建所谓的报告查询(准确提取您需要的数据,而不是构建整个对象)。详情见链接rongou.blogspot.com/2005/08/hibernate-report-query.html
    • 哦,我不知道报告查询,这很有趣。 Hibernate 的全部意义当然是将数据从表映射到对象,但对于某些应用程序来说,表更适合,而报表查询似乎正好适合这一点。
    • 你是对的。我需要 HQL 的逆向工程来作为我们报告模块的控制器。
    【解决方案2】:

    我为我的问题找到了正确的解决方案。除了那部分之外,您的原始帖子几乎是正确的:

    if(node.getType() == SqlTokenTypes.FROM_FRAGMENT || node.getType() == SqlTokenTypes.JOIN_FRAGMENT) {
     FromElement id = (FromElement)node;
     System.out.println(node+": "+id.getClassAlias()+" - "+id.getClassName());
    }
    

    请更正你的答案,我接受。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2023-03-18
      • 1970-01-01
      • 1970-01-01
      • 2011-08-02
      • 2020-05-25
      • 2015-11-21
      • 2017-12-24
      相关资源
      最近更新 更多