与HQL的多对多关系的次优查询

时间:2011-07-07 13:03:26

标签: nhibernate many-to-many hql

我有两个实体,位置和行业,以及它们之间的链接表。我在两个实体之间在两个方向上配置了多对多关系。

在搜索查询中,我正在尝试选择与行业列表相关联的地理位置。

经过几天和几天尝试纠缠标准API之后,我决定下载到HQL并放弃标准API。但即使这样对我来说也不顺利 - 看来,无论我是手写这个HQL查询,还是让标准API这样做,我都会得到相同的结果。

我设法以两种方式产生了正确的结果 - 像这样:

var q = Data.Query("select distinct loc from Location loc join loc.Industries ind where ind in (:ind)");

q.SetParameterList("ind", new Industry[] { Data.GetIndustry(4), Data.GetIndustry(5) });

并且(更好)那样:

var q = Data.Query("select distinct loc from Location loc join loc.Industries ind where ind.id in (:ind)");

q.SetParameterList("ind", new int[] { 4, 5 });

不幸的是,两者都导致次优查询:

select distinct
  location0_.Id as Id16_,
  location0_.Name as Name16_,
  (etc.)
from Location location0_
  inner join LocationIndustry industries1_
    on location0_.Id=industries1_.LocationId
  inner join Industry industry2_
    on industries1_.IndustryId=industry2_.Id
where
  industry2_.Id in (? , ?)

为什么要额外加入?

NH不够聪明,不知道作为查询中涉及的唯一行业属性的Industry.Id属性存储在LocationIndustry链接表中,并且不需要额外加入到Industry表中本身?

或者我做错了什么?

理想情况下,对我来说最直观的是写:

from Location loc where loc.Industries in (:ind)

这不起作用 - 它会抛出一个错误并说它不知道Industries属性。我想因为作为编程术语中的“财产”的工业实际上是DBMS方面的“关系”。

在HQL中编写此查询的最简单,最有效的方法是什么?

谢谢!

1 个答案:

答案 0 :(得分:2)

根据您使用的映射策略,我不确定您是否可以避免这种额外的连接。

你可以通过使用中间类来避免它,但这意味着你需要一个像这样的类结构:

public class Industry {
    //Other stuff
    public virtual List<LocationIndustry> LocationIndustries {get; set:;}
}

public class LocationIndustry {
    public virtual Location Location {get; set;}
    public virtual Industry Industry {get; set;}
}

public class Location {
    //normal stuff
    public virtual IList<LocationIndustry> LocationIndustries {get; set;}
}

然后,您可以查询LocationIndustry课程,并避免加入Location