我正在开发一个.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语句。
任何帮助将不胜感激!
答案 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
那么它也使用旧的语法。