为什么直接在HQL中使用列名有时只能工作?

时间:2010-10-12 17:18:11

标签: nhibernate hibernate hql

我有两个HQL查询用于快速和脏的单元测试。第一个看起来有点像这样:

from Foo where SOME_FOREIGN_KEY = 42

第二个看起来像这样:

from Foo as foo
 inner join foo.Bar as bar
 where foo.SOME_FOREIGN_KEY = 42

SOME_FOREIGN_KEY列不是Hibernate知道的映射名称。

由于某种原因,第一个HQL查询有效,但第二个没有。

我的目标是让第二个版本工作,而无需将对象图遍历到外键标识的对象。对于此测试,我有一个已知的ID,我只想要与该ID相关的对象。关系另一端的对象本身是无关紧要的。这可能吗?

2 个答案:

答案 0 :(得分:8)

  

由于某种原因,第一个HQL查询有效,但第二个没有。

当您在HQL查询的WHERE子句中使用Hibernate不知道的内容时(例如,未在SQL方言中注册的函数),Hibernate行为灵巧,直接传递它到数据库

换句话说,假设Foo映射到TABLE_FOO,则以下HQL

from Foo where SOME_FOREIGN_KEY = 42

被翻译成以下SQL

SELECT FROM TABLE_FOO WHERE SOME_FOREIGN_KEY = 42

如果TABLE_FOO实际上有SOME_FOREIGN_KEY列,则可以使用。

但是,在使用第二个示例中的别名时:

from Foo as foo where foo.SOME_FOREIGN_KEY = 42

Hibernate尝试将SOME_FOREIGN_KEY解析为Foo实体的属性,这显然会失败。

  

我的目标是让第二个版本正常工作,而无需将对象图遍历到外键标识的对象。

如果您在列前添加别名,则不会。所以以下内容应该有效:

from Foo as foo
 inner join foo.Bar as bar
 where SOME_FOREIGN_KEY = 42

但老实说,我不明白为什么你不想使用路径表达式,我建议不要使用上述解决方案。 HQL的一个重点是抽象表名和列名,你将在这里完全击败这个目标。

答案 1 :(得分:1)

所以第一个例子中的Foo没有别名,第二个例子就是。这意味着在第二个例子中,Hibernate正在寻找'foo'的属性。这应该是答案。

也许这会奏效:

      select  f
      from    Foo f
      inner join f.Bar bar
      where   f.SomeForeignKeyId = 42

SomeForeignKeyId是映射到SOME_FOREIGN_KEY的属性,无论哪种方式,您都必须通过引用实体的Id字段执行此操作。

同样在第一个示例中获取Foo,应该可以正常工作,具体取决于您的映射。因此,如果在您的映射中您有Eager提取,那么这应该是我所知道的。