自动加入NHibernate /多对一/ HQL

时间:2010-07-21 09:26:30

标签: c# .net nhibernate hql

我正在开发一个.NET C#项目,我必须使用NHibernate Mapping Attributes将我的对象映射到我数据库中的表。

现在让我们解释一下我的问题。

我有两个映射类,例如ClassA和ClassB。在我的数据库中,表A包含引用表B的主键的外键。因此,我已经向ClassA添加了多对一映射的ClassB实例:

private ClassB b;
[ManyToOne(0, Name = "B", Column = "ID_TABLE_B_TABLE_A", Class = "ClassB", Update = false, Insert = false)]
public virtual ClassB B 
{ 
    get { return b; } 
    set { b= value; } 
}

现在,我想在访问ClassA时检查ClassB字段的值。我在HQL中编写查询:

Session.CreateQuery("select a.Id from ClassA a where a.ClassB.Name = 'xxx' ");

这是生成的SQL:

select tablea0_.ID_TABLE_A as col_0_0_ 
from TABLE_A tablea0_, TABLE_B tableb1_
where tablea0_.ID_TABLE_B_TABLE_A = tableb1_.ID_TABLE_B 
and tableb1_.NAME_TABLE_B='xxx'

我认为这种HQL查询应该生成一个join语句而不是where语句,因为我已经定义了两个类之间的多对一关联。这样的事情会更好:

select tablea0_.ID_TABLE_A as col_0_0_ 
from TABLE_A tablea0_ 
left join TABLE_B tableb1_ on tableb1_.ID_TABLE_B = tablea0_.ID_TABLE_B_TABLE_A 
where tableb1_.NAME_TABLE_B='xxx'

在我看来,加入看起来比较干净。我想知道是否有一种方法可以相应地设置NHibernate的行为,而无需在HQL查询中明确指定join语句。

任何帮助将不胜感激!

3 个答案:

答案 0 :(得分:1)

联接的工作原理如下:

Session.CreateQuery("select a.Id from ClassA a join a.ClassB b where b.Name = 'xxx' ");
Session.CreateQuery("select a.Id from ClassA a left join a.ClassB b where b.Name = 'xxx' ");
Session.CreateQuery("select a.Id from ClassA a left outer join a.ClassB b where b.Name = 'xxx' ");

当然,现在您可以找出最适合您的联接。 :)

更多信息@ http://docs.jboss.org/hibernate/stable/core/reference/en/html/queryhql.html#queryhql-joins

另外,如果你想成为一个很酷的孩子,你可以随时使用Linq来NHibernate:

var result = Session.Linq<ClassA>().Where(a => a.B.Name == 'xxx').ToList();

会生成内部联接查询。

答案 1 :(得分:0)

自从我使用NHibernate以来已经有一段时间了,但我认为你不能强迫它这样做。

您可以尝试在多对一映射中指定“fetch = join”,但是如果内存服务,这只会改变NHibernate在获取相关实体时使用的策略,而不是如何将自定义HQL查询转换为SQL

但为什么甚至担心呢? 在99%的情况下,我实际上查看了生成的SQL,这是因为生成了错误的SQL(通常是因为犯了错误),或者调查了性能问题。

答案 2 :(得分:0)

生成的SQL取决于数据库方言。 Oracle直到9i才支持ANSI连接语法,因此NHibernate中的Oracle方言仍然可以使用旧语法进行内连接。左连接生成什么SQL?如果它是tablea0_.ID_TABLE_B_TABLE_A += tableb1_.ID_TABLE_B那么它也使用旧的语法。