【问题标题】:Raw SQL in Grails using hibernate session :Error使用休眠会话的 Grails 中的原始 SQL:错误
【发布时间】:2014-12-18 08:04:58
【问题描述】:

我正在尝试使用休眠会话在 grails 中执行此 SQL。此 SQL 将返回工件表中的内容。这段代码有什么问题?

final session = sessionFactory.getCurrentSession();
final  String query  = "select a.* from classification c join (select id from taxonomy_node "+ 
                                                        "start with id = :nodeId connect by nocycle prior id = parent_id) h " +
                                                        "on (c.node.id = h.id) join artifact a on (a.id = c.artifact_id) " +
                                                        "Where a.DOCUMENT.ID = :docid AND c.active=1 ";
final sqlQuery = session.createSQLQuery(query);
artifact = sqlQuery.with {
        addEntity(Artifact, Classificatio, TaxonomyNode);
        setLong('nodeId',filterByAssociatedNodeId);
        setLong('docid',document.id);       
        list();
}

我得到的错误

groovy.lang.MissingPropertyException: No such property: sessionFactory for class: com.th.ald.aeandsdx.ArtifactController

我还尝试了一些其他方法,例如将这个 sql 转换为 HQL,如 convert sql to hql

【问题讨论】:

    标签: sql oracle hibernate grails hql


    【解决方案1】:

    这是我一段时间以来见过的最奇怪的问题。看看你的第一行代码。阅读您向我们展示的错误消息。你为什么要看那一行代码以外的东西?

    您正在使用一个没有值的变量。这不是数据库问题,不是 SQL 与 HQL 问题,不是 Grails 问题,只是一个普通的无聊编程问题。分配一个有效值并继续:)

    但是我们如何获得这个神秘的sessionFactory 的缺失值呢? SessionFactory 是一个单例 Spring bean,所以依赖注入是你最好的选择。如果您在支持依赖注入的服务、控制器、域类或其他工件类型中运行它,请在类中添加字段范围变量,例如

    class MyService {...
    
       def sessionFactory
    
       def someMethod(int foo, boolean bar) {
          ...
       }
    
       ...
    }
    

    之所以可行,是因为 Grails 使用名称自动注入,并且像这样的属性有一个由 Groovy 编译器生成的 setter 方法,Spring 会看到并调用它来注入 bean 实例,并且您可以通过第 1 行。

    但它在方法内部不起作用。如果在方法中添加def someBeanName,它是一个局部变量,而不是类属性,所以它对 Spring 不可见,并且将为 null。

    【讨论】:

    • 谢谢。在类中定义会话工厂而不是方法工作。 setLong 方法有问题 我收到错误消息 groovy.lang.MissingMethodException: No signature of method: com.thomsonreuters.ald.aeandsdx.ArtifactController.setLong() is applicable for argument types: (java.lang.String , java.lang.String) 值:[nodeId, 5067]
    • 再一次,错误很清楚,就在你面前:) 方法是setLong,所以你希望第二个参数是一个数字。该值看起来像一个数字,但它告诉您您传递了一个字符串。所以转换它。有几种方法,我会使用as 运算符setLong('docid',document.id as Long)
    • 弹出新错误。我想知道将其转换为 HQL 会不会更容易?并使用 findall /executeQuery 因为我正在尝试进行分页
    • 我不知道这是什么意思 groovy.lang.MissingPropertyException: No such property: artifact for class: com..ald.aeandsdx.ArtifactController
    • 我想是时候提出一个新问题了,这个问题已经满了
    【解决方案2】:

    您使用“final”的任何特殊原因?

    无论如何,不​​确定这是否是一个问题,这是我可以从需要原始 SQL 的类似情况中推荐的内容。我返回了一个 Map 而不是一组对象,我遇到了问题,因为我没有在我的域类中定义关系并以传统方式利用 GORM。

    我要更改的代码是:

    final sqlQuery = session.createSQLQuery(query).setResultTransformer(AliasToEntityMapResultTransformer.INSTANCE)
    .addScalar("ALIAS_VALUE_FROM_SELECT", new StringType())
    .addScalar("ALIAS_VALUE_FROM_SELECT", new TimestampType())
    .addScalar("ALIAS_VALUE_FROM_SELECT", new BooleanType())
    .addScalar("ALIAS_VALUE_FROM_SELECT", new ShortType())
    .addScalar("ALIAS_VALUE_FROM_SELECT", new LongType())
    

    确保为您的列设置别名并列出它们而不是 a.*,addScalar 包含您需要的所有类型,这样您可以确保您拥有正确的类型。这有点冗长,但这样至少你会得到你期望的结果。

    List<Map<String,Object>> artifact = sqlQuery.list()
    

    我认为它是对象列表还是地图列表并不重要,最终您会得到适合您的结果。

    【讨论】:

      猜你喜欢
      • 2015-08-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-05-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多