我有两个实体,位置和行业,以及它们之间的链接表。我在两个实体之间在两个方向上配置了多对多关系。
在搜索查询中,我正在尝试选择与行业列表相关联的地理位置。
经过几天和几天尝试纠缠标准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中编写此查询的最简单,最有效的方法是什么?
谢谢!
答案 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
。