我有两个实体,Location和Industry,以及它们之间的链接表。我已经在两个实体之间配置了双向的多对多关系。
在搜索查询中,我尝试选择与行业列表相关联的位置。
经过一天又一天的努力,我决定放弃criteria API,转而使用HQL。但即使这样对我来说也不是很顺利-似乎无论我是手写这个HQL查询,还是让criteria 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链接表中,并且不需要额外的连接到行业表本身?
还是我做错了什么?
理想情况下,对我来说最直观的事情应该是这样写:
from Location loc where loc.Industries in (:ind)这不起作用-它抛出一个错误,并说它不知道工业属性。我猜是因为行业,在编程术语中是一个“资产”,在DBMS中实际上是一个“关系”。
用HQL编写此查询的最简单、最有效的方法是什么?
谢谢!
发布于 2011-07-07 21:13:20
考虑到您所使用的映射策略,我不确定您是否能避免这种额外的连接。
您可以通过使用中介类来避免它,但这意味着您将需要如下的类结构:
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。
https://stackoverflow.com/questions/6611035
复制相似问题