2016-08-31 58 views
0

全部,HQL左侧加入生成的SQL不正确 - 左侧加入错误的位置

使用Nhibernate版本3.3.3 GA。

我创建的HQL未正确转换为SQL。具体而言, 其中一个左连接(位于计划:Job_Plans表和分区:Code_Plan_Division_Types表之间)以where子句中的内连接结束。

换句话说,而不是这样的:

... 
from Job_Info project_0_ 
left outer join Job_Plans planlist5_ on project_0_.entity_id=planlist5_.job_id 
left outer join Code_Plan_Division_Types plandivisi18_ on planlist5_.division_id=plandivisi18_.entity_id 

我得到这个:

... 
from Job_Info project_0_ 
left outer join Job_Plans planlist5_ on project_0_.entity_id=planlist5_.job_id, 
Code_Plan_Division_Types plandivisi18_ 
where 
planlist5_.division_id=plandivisi18_.entity_id 

这里是我的完整查询:

HQL:

select p, plans from Project_ p 
    inner join fetch p.Client 
    inner join fetch p.ProjectType 
    left join fetch p.Office 
    left join fetch p.Region 

    left join p.PlanList plans 
    left join fetch plans.PlanType 
    left join fetch plans.ProjectType 
    left join fetch plans.Quadrant 
    left join fetch plans.Division 
    left join fetch plans.County 
    left join fetch plans.Municipality 
    left join fetch plans.Township 

    where p.id in (select p.id 
    from Project_ p 
     left join p.PlanList plans 
     left join p.ReferencePlanList rplans 
     left join p.AddressList addr 
     left join p.ImageSets imgs 
    where p.Status = true and p.Region.Id = :region) 

    and plans.PlanNumber like :planNo 


    order by plans.PlanNumber asc, plans.Division.Code asc, replace((coalesce(plans.Lot, '')+coalesce(plans.PartLot, '')), '-', ' ') asc, replace((coalesce(plans.Block, '')+coalesce(plans.PartBlock, '')), '-', ' ') asc 

生成SQL:

select TOP (100) 
project_0_.entity_id as entity1_20_0_, planlist5_.entity_id as entity1_76_1_, client_1_.entity_id as entity1_11_2_, projecttyp2_.entity_id as entity1_54_3_, office_3_.entity_id as entity1_55_4_, region_4_.entity_id as entity1_1_5_, plantype_6_.entity_id as entity1_21_6_, projecttyp7_.entity_id as entity1_54_7_, quadrant_8_.entity_id as entity1_2_8_, plandivisi9_.entity_id as entity1_12_9_, county_10_.entity_id as entity1_22_10_, municipali11_.entity_id as entity1_3_11_, township_12_.entity_id as entity1_30_12_, project_0_.plan_attached as plan2_20_0_, project_0_.notes_attached as notes3_20_0_, project_0_.status as status20_0_, project_0_.file_number as file5_20_0_, project_0_.order_date as order6_20_0_, project_0_.due_date as due7_20_0_, project_0_.due_date_fw as due8_20_0_, project_0_.lock_status as lock9_20_0_, project_0_.currency_code as currency10_20_0_, project_0_.client_reference as client11_20_0_, project_0_.pin as pin20_0_, project_0_.office_id as office13_20_0_, project_0_.job_type_id as job14_20_0_, project_0_.client_entity_id as client15_20_0_, project_0_.region_id as region16_20_0_, planlist5_.lot as lot76_1_, planlist5_.part_lot as part3_76_1_, planlist5_.lot_search as lot4_76_1_, planlist5_.block as block76_1_, planlist5_.part_block as part6_76_1_, planlist5_.plan_number as plan7_76_1_, planlist5_.section_num as section8_76_1_, planlist5_.township as township76_1_, planlist5_.range_num as range10_76_1_, planlist5_.meridian_id as meridian11_76_1_, planlist5_.job_id as job12_76_1_, planlist5_.plan_id as plan13_76_1_, planlist5_.job_type_id as job14_76_1_, planlist5_.quadrant_id as quadrant15_76_1_, planlist5_.division_id as division16_76_1_, planlist5_.county_id as county17_76_1_, planlist5_.municipality_id as municip18_76_1_, planlist5_.township_id as township19_76_1_, client_1_.status as status11_2_, client_1_.client_number as client3_11_2_, client_1_.client_name as client4_11_2_, projecttyp2_.name as name54_3_, projecttyp2_.description as descript3_54_3_, office_3_.name as name55_4_, office_3_.description as descript3_55_4_, region_4_.name as name1_5_, region_4_.description as descript7_1_5_, region_4_.country_id as country8_1_5_, plantype_6_.name as name21_6_, plantype_6_.description as descript3_21_6_, plantype_6_.display as display21_6_, projecttyp7_.name as name54_7_, projecttyp7_.description as descript3_54_7_, quadrant_8_.name as name2_8_, quadrant_8_.description as descript7_2_8_, plandivisi9_.name as name12_9_, plandivisi9_.description as descript7_12_9_, plandivisi9_.display as display12_9_, county_10_.name as name22_10_, county_10_.description as descript3_22_10_, county_10_.region_id as region4_22_10_, municipali11_.name as name3_11_, municipali11_.description as descript7_3_11_, municipali11_.county_id as county11_3_11_, township_12_.name as name30_12_, township_12_.description as descript3_30_12_, township_12_.county_id as county4_30_12_ 

from Job_Info project_0_ 
inner join Companies client_1_ on project_0_.client_entity_id=client_1_.entity_id 
inner join Code_Job_Types projecttyp2_ on project_0_.job_type_id=projecttyp2_.entity_id 
left outer join code_office_types office_3_ on project_0_.office_id=office_3_.entity_id 
left outer join Code_Region_Types region_4_ on project_0_.region_id=region_4_.entity_id 
left outer join Job_Plans planlist5_ on project_0_.entity_id=planlist5_.job_id 
left outer join Code_Plan_ID_Types plantype_6_ on planlist5_.plan_id=plantype_6_.entity_id 
left outer join Code_Job_Types projecttyp7_ on planlist5_.job_type_id=projecttyp7_.entity_id 
left outer join Code_Quadrant_Types quadrant_8_ on planlist5_.quadrant_id=quadrant_8_.entity_id 
left outer join Code_Plan_Division_Types plandivisi9_ on planlist5_.division_id=plandivisi9_.entity_id 
left outer join code_county_types county_10_ on planlist5_.county_id=county_10_.entity_id 
left outer join Code_Municipality_Types municipali11_ on planlist5_.municipality_id=municipali11_.entity_id 
left outer join Code_Township_Types township_12_ on planlist5_.township_id=township_12_.entity_id, 
Code_Plan_Division_Types plandivisi18_ 


where planlist5_.division_id=plandivisi18_.entity_id 
and (project_0_.entity_id in 


(select project_13_.entity_id 
from Job_Info project_13_ 
left outer join Job_Plans planlist14_ on project_13_.entity_id=planlist14_.job_id 
left outer join Job_Underlying_Rplan referencep15_ on project_13_.entity_id=referencep15_.job_id 
left outer join Job_Address addresslis16_ on project_13_.entity_id=addresslis16_.JobId 
left outer join Job_Images_Set imagesets17_ on project_13_.entity_id=imagesets17_.job_id 
where project_13_.status=1 and project_13_.region_id=1)) 
and (planlist5_.plan_number like '%plan%') 

order by planlist5_.plan_number asc, plandivisi18_.name asc, replace(coalesce(planlist5_.lot, '')+coalesce(planlist5_.part_lot, ''), '-', ' ') asc, replace(coalesce(planlist5_.block, '')+coalesce(planlist5_.part_block, ''), '-', ' ') asc 

UPDATE: 找到了症结:我不应该由我为了引用plans.Division.Code(甚至where子句),因为“取”关键字。请参阅答案了解更多详情。

原因是order by子句。通过从查询中排除plans.Division.Code命令的顺序现在是正确的。更改后的顺序是:

HQL:

order by plans.PlanNumber asc, replace((coalesce(plans.Lot, '')+coalesce(plans.PartLot, '')), '-', ' ') asc, replace((coalesce(plans.Block, '')+coalesce(plans.PartBlock, '')), '-', ' ') asc 

生成的SQL:

order by planlist5_.plan_number asc, replace(coalesce(planlist5_.lot, '')+coalesce(planlist5_.part_lot, ''), '-', ' ') asc, replace(coalesce(planlist5_.block, '')+coalesce(planlist5_.part_block, ''), '-', ' ') asc 
+0

这是一个生成的HQL吗?它在子查询中的冗余连接看起来有点奇怪。 另外,在某种程度上,“计划”成为您渴望获取的一部分,并且这样的连接不应该用于除了获取之外的其他任何事情。 – gliljas

+0

HQL是手写的,看起来有点奇怪,但给我最好的表现(根据我的测试结果)。为什么在内部查询中存在冗余连接的原因是出于两个原因:1)我在内部查询中进行了更多筛选,需要那些连接进行筛选,2)稍后更好地设计/重构 - 有很多筛选动态地完成,但您不需要看到这个来解决我有HQL到SQL的问题。 – ActiveX

+0

“另外,从某种意义上说,”计划“成为你渴望获取的一部分,而这样的连接永远不应该用于其他任何事情。”那么,所以你基本上说,如果我需要对任何“热切”的获取连接执行筛选,则需要另一个非热切的获取连接?如果这是真的,我的查询将增加一倍。有没有文档参考?如果是的话,请指向我。我所观察到的,基于我的过滤瓦特/急切的提取联接是它的工作瓦特/这一个例外, - 而不是其中的问题,它的顺序。 – ActiveX

回答

0

这更多的是一种工作的周围,而不是修复。因为引用这个问题的顺序引用了分割实体,所以我决定创建另一个(冗余)连接到同一个分割实体(非获取连接,所以它不出现在select中)并带有别名'div'。然后我按顺序使用别名。

order by plans.PlanNumber asc, div.Code 

这个技巧足以解决这个问题。我希望这是固定在nhibernate。顺便说一下,这个问题仍然存在于3.4.1 GA中。我无法使用4.x版本,因为我目前绑定了.NET 2.0。

更新: 好吧,事实证明它不是一个错误, - 我使用的是“fetch”关键字w /我不应该使用的东西。

这里有一个答案,从NHibernate的群体,我的问题:

根据Hibernate的文档:“一个fetch连接通常不需要被指定别名,因为相关联的对象不应当在where子句中使用(或任何其他条款)。“

主要原因是“抓取”意味着渴望加载和水合一个对象,这样的集合不应该被过滤,因为那样你的对象将处于不一致的状态。