2010-06-23 4 views
5

나는 nHibernate 2.1.2를 사용하고 있으며, nhibernate가 중첩 된 many-to-one 엔터티에 left outer join을 생성 할 것이라고 확신했다. 엔티티 Organization에서 시작하는 3 번째 중첩 된 노트에서 왼쪽 - 외부 조인을 시작하는 것으로 보입니다. 나는 매핑 파일에서 강제로 내부 조인을 사용하도록 다음과 같이 설정했습니다. 매핑 파일에서 빠진 항목이 있습니까? 정말로 누군가가 나에게이 점에 대한 힌트를 줄 수 있기를 바랍니다. 어떤 도움을 주셔서 감사합니다!nhibernate는 many-to-one 엔터티에 왼쪽 outer join을 생성한다.

lazy="false" fetch="join" 

예 Entites와의 관계 : 판매 기록 - 직원 - 기관

NHibernate에 생성 :

select... 
from sales 
inner join employee 
left outer join organization 

Sales.hbm.xml

<many-to-one name="Employee" insert="true" update="true" access="field.pascalcase-underscore" not-null="true" lazy="false" fetch="join"/> 
<column name="EmployeeId" not-null="true"/> 
</many-to-one> 

Employee.hbm.xml

<many-to-one name="Organization" insert="true" update="true" access="field.pascalcase-underscore" not-null="true" lazy="false" fetch="join"/> 
<column name="OrgId" not-null="true"/> 
</many-to-one> 
+1

쿼리는 어떻게 생겼습니까? HQL이나 기준을 사용하고 있습니까? –

+0

난 그냥 엔터티를 수행합니다. 가져 오기, 내가 너무 똑같은 문제와 HQL 테스트 btw. – ksang

+0

나는 수정 된 nhibernate 소스에 의해이 문제를 해결했다. nhibernate가 첫 번째 레벨의 join을 위해서만 innerjoint sql을 생성한다는 것을 알았다. 어쩌면 누군가가 왜 그런 식으로 행동하는지 말할 수 있습니다. – ksang

답변

4

자 NHibernate는 내부 않는 경우 부모 테이블에서 아이 ID에서 ID를하지 않습니다 (하지만 그들은 같은 것)에 가입.

예 :

TableParent (ID, Name) 
    TableChild (ID, ID_TableParent, ....) 

nHibernate 수는 내부 조인 않는 경우, 당신은 얻을 : nHibernate 수는 왼쪽 외부 조인 않는 경우

select c.ID, c.ID_TableParent, p.Name 
from TableChild c 
inner join TableParent p on p.ID = c.ID_TableParent 

, 당신은 얻을 :

select c.ID, c.ID_TableParent, p.ID, p.Name 
from TableChild c 
left outer join TableParent p on p.ID = c.ID_TableParent 

때문에를 Hibernate의 내부 동작 중 두 번째 질의로부터 2 개의 엔티티를 생성 할 수있다. TableChild 및 TableParent에 대한 하나의 엔터티.

첫 번째 쿼리에서는 TableChild 엔티티 만 가져오고 어떤 경우에는 p.Name이 무시되고 (두 번째 수준에서 probalby) TableParent를 참조하는 속성을 검사 할 때 데이터베이스가 다시 쿼리됩니다. NHibernate.SqlCommand으로

SysPermissionTree t = null; 
SysPermission p = null; 

return db.QueryOver<SysPermissionTree>() 
     .JoinAlias(x => x.Children,() => t, NHibernate.SqlCommand.JoinType.LeftOuterJoin) 
     .JoinAlias(() => t.Permissions,() => p, NHibernate.SqlCommand.JoinType.LeftOuterJoin) 
     .Where(x => x.Parent == null) 
     .TransformUsing(Transformers.DistinctRootEntity) 
     .List(); 

:

public class SysPermissionTree 
{ 
    public virtual int ID { get; set; } 
    public virtual SysPermissionTree Parent { get; set; } 
    public virtual string Name_L1 { get; set; } 
    public virtual string Name_L2 { get; set; } 

    public virtual Iesi.Collections.Generic.ISet<SysPermissionTree> Children { get; private set; } 
    public virtual Iesi.Collections.Generic.ISet<SysPermission> Permissions { get; private set; } 

    public class SysPermissionTree_Map : ClassMap<SysPermissionTree> 
    { 
     public SysPermissionTree_Map() 
     { 
      Id(x => x.ID).GeneratedBy.Identity(); 

      References(x => x.Parent, "id_SysPermissionTree_Parent"); 
      Map(x => x.Name_L1); 
      Map(x => x.Name_L2); 
      HasMany(x => x.Children).KeyColumn("id_SysPermissionTree_Parent").AsSet(); 
      HasMany(x => x.Permissions).KeyColumn("id_SysPermissionTree").AsSet(); 
     } 
    } 
} 

그리고 내가 사용하는 쿼리이 있었다 : 나는 데이터베이스에 하나 개의 히트와 함께 트리 구조를로드하고 싶어 할 때

나는 밖으로 이걸 발견 .JoinType.LeftOuterJoin. 왜냐하면 InnerJoin을 사용하면 구조가 하나의 쿼리만으로로드되지 않기 때문입니다. NHibernate가 엔티티를 인식하도록 LeftOuterJoin을 사용해야했습니다. 실행

SQL 쿼리했다 :

가 첫 번째 쿼리가 외부를 남겨
SELECT this_.ID as ID28_2_, this_.Name_L1 as Name2_28_2_, this_.Name_L2 as Name3_28_2_, this_.id_SysPermissionTree_Parent as id4_28_2_, t1_.id_SysPermissionTree_Parent as id4_4_, t1_.ID as ID4_, t1_.ID as ID28_0_, t1_.Name_L1 as Name2_28_0_, t1_.Name_L2 as Name3_28_0_, t1_.id_SysPermissionTree_Parent as id4_28_0_, p2_.id_SysPermissionTree as id4_5_, p2_.ID as ID5_, p2_.ID as ID27_1_, p2_.Name_L1 as Name2_27_1_, p2_.Name_L2 as Name3_27_1_, p2_.id_SysPermissionTree as id4_27_1_ FROM [SysPermissionTree] this_ left outer join [SysPermissionTree] t1_ on this_.ID=t1_.id_SysPermissionTree_Parent left outer join [SysPermission] p2_ on t1_.ID=p2_.id_SysPermissionTree WHERE this_.id_SysPermissionTree_Parent is null 
SELECT this_.ID as ID28_2_, this_.Name_L1 as Name2_28_2_, this_.Name_L2 as Name3_28_2_, this_.id_SysPermissionTree_Parent as id4_28_2_, t1_.ID as ID28_0_, t1_.Name_L1 as Name2_28_0_, t1_.Name_L2 as Name3_28_0_, t1_.id_SysPermissionTree_Parent as id4_28_0_, p2_.ID as ID27_1_, p2_.Name_L1 as Name2_27_1_, p2_.Name_L2 as Name3_27_1_, p2_.id_SysPermissionTree as id4_27_1_ FROM [SysPermissionTree] this_ inner join [SysPermissionTree] t1_ on this_.ID=t1_.id_SysPermissionTree_Parent inner join [SysPermission] p2_ on t1_.ID=p2_.id_SysPermissionTree WHERE this_.id_SysPermissionTree_Parent is null 

가입하고 우리가이 개 추가 필드를 얻을 : t1_.id_SysPermissionTree_Parent를 id4_4_로, t1_.ID을 ID4_

그래서 내가 당신에게 말하려고하면 NHibernate를 사용한다면 왼쪽 외부 조인은 때때로 NHibernate의 내부 동작을 따라야 만하는 것입니다.

관련 문제