2011-08-02 2 views
1

私は、SecurityContactと呼ばれるテーブルを持っています。これは、別のテーブル連絡先と多対1の関係を持っています。連絡先には2つの結合列があり、そのうちの1つはagentContactと呼ばれ、もう1つはauditContactです。私は、次のHQLクエリを実行しようとしています:LEFT JOINを無視している休止状態

SELECT sc FROM SecurityContact sc LEFT JOIN sc.agentContact ac LEFT JOIN sc.auditContact ac2 WHERE sc.securityId=:securityId2 

しかし、休止状態に完全LEFTは、文のJOIN無視し、内部結合を利用SQLを生成するために進みます。これは私の目的にはまったく合っていません。私は幸運のない注釈の設定を試みました。この問題は2日以上私を狂わせてしまったので、助けを借りれば大いに感謝します。ここで

は私のSecurityContactクラスのコードです:あなたのHQL join syntaxがグラグラに見える

select securityco0_.agent_id as col_0_0_, securityco0_.audit_id as col_1_0_, securityco0_.create_date as col_2_0_, securityco0_.create_user as col_3_0_, securityco0_.modify_date as col_4_0_, securityco0_.modify_user as col_5_0_, securityco0_.securityContact_id as col_6_0_, securityco0_.security_id as col_7_0_, agentconta3_.contact_id as contact1_0_0_, agentconta4_.contact_id as contact1_0_1_, agentconta3_.bank_id as bank10_0_0_, agentconta3_.create_date as create2_0_0_, agentconta3_.create_user as create3_0_0_, agentconta3_.email as email0_0_, agentconta3_.fax as fax0_0_, agentconta3_.modify_date as modify6_0_0_, agentconta3_.modify_user as modify7_0_0_, agentconta3_.name as name0_0_, agentconta3_.phone as phone0_0_, agentconta4_.bank_id as bank10_0_1_, agentconta4_.create_date as create2_0_1_, agentconta4_.create_user as create3_0_1_, agentconta4_.email as email0_1_, agentconta4_.fax as fax0_1_, agentconta4_.modify_date as modify6_0_1_, agentconta4_.modify_user as modify7_0_1_, agentconta4_.name as name0_1_, agentconta4_.phone as phone0_1_ from SecurityContact securityco0_ left outer join AgentContact agentconta1_ on securityco0_.agent_id=agentconta1_.contact_id left outer join AgentContact agentconta2_ on securityco0_.audit_id=agentconta2_.contact_id inner join AgentContact agentconta3_ on securityco0_.agent_id=agentconta3_.contact_id inner join AgentContact agentconta4_ on securityco0_.audit_id=agentconta4_.contact_id where securityco0_.security_id=? 
+0

ここでは、Hibernateで左結合を使用すると問題はありますか?あなたはHQLクエリで何を質問していますか?どのような結果が、単純な 'securityContact from securityId =? 'と違うと思いますか? –

+0

@matt利用可能な対応するagentContactまたはauditContactがなくても、Hibernateがエントリを返すようにしたいので重要です。それは内部結合でそれをしません。 –

+0

ですが、デフォルトでは '@ ManyToOne'の関連付けはオプション/ NULL可能ではありませんか?この関係の反対側は、他のクラスではどのように見えますか?単純な 'session.get(SecurityContact.class、securityId)'はどちらのフィールドもnullであるインスタンスを返さないと言っていますか? –

答えて

1

私はあなたの問題に関してはいくつかのテストを行ってきた、そしてあなたがあなたが休止状態の(時代遅れの)バージョンでは、あなたのマッピングに問題やバグのいずれかを持っている必要がありますように私には思えますを使用して。任意@ManyToOne協会

は既に左を使用しなければならないHibernateはエンティティを照会するために参加し、それが関連(それが関連するエンティティがヌルであるか否かをルートエンティティを照会するための唯一の方法であるように)です。

私は、これを図解するサンプルプロジェクトをhttps://github.com/mattnworb/hibernate-sampleに投げました。私のサンプルプロジェクトで

は、Employeeクラスはa unidirectional many-to-one mapping to the Team class有する:ユニットテストにおいて

/** 
* Unidirectional relationship between Employee and Team. 
*/ 
@ManyToOne 
@JoinColumn(name = "team_id") 
private Team team; 

、テストの両方が存在することをDBテーブルにそのEmployee.teamis null when not setをアサートEmployee.team参照is not-null when it is set in the DB、及び別の試験。

さらに、同様のテストを行って、CompanyEmployeeエンティティの間に同様の双方向の関係があります。

最後に、ログに私は(簡単なsession.get(Employee.class, id)付き)EmployeeエンティティのHibernateクエリが、それは左を使用する場合teamsテーブルに引き出すために参加していることがわかります(私が追加された行は、自分自身を壊す):

DEBUGのorg.hibernate.SQL - id1_2_としてemployee0_.id選択は、employme3_1_2_としてdateOfBi2_1_2_、employee0_.employmentStartDateとして、company6_1_2_としてemployee0_.dateOfBirthをemployee0_.company_id、firstName1_2_、lastName1_2_としてemployee0_.lastNameとしてemployee0_.firstNameは、としてemployee0_.team_id team7_1_2_、company1_.idをid0_0_、company1_.nameをname0_0_、team2_.idをid2_1_、team2_.nameをname2_1_
からemp loyees employee0_
左外部結合企業company1_ on employee0_.company_id = company1_.id
left外部結合チームteam2_ on employee0_.team_id = team2_.id where employee0_.id =?

限りの関係は、オプションとして設定されているとして、あなたの関連するエンティティ間の結合ので合計では、Hibernateは左を使用するためには、特別なHQLは全くクエリの必要はないはずです - シンプルsession.get()ルートエンティティは、左の結合で関連するエンティティのテーブルをクエリする必要があります。結果が異なる場合は、Hibernateのバージョンにバグがあります(ここでは3.6.6.Finalを使用しています)、またはマッピングに誤りがあることを示唆しています。

1

:ここ

/** 
* The persistent class for the SecurityContact database table. 
* 
*/ 
@Entity 
@FXClass(kind=FXClassKind.REMOTE) 
public class SecurityContact implements Serializable { 
    private static final long serialVersionUID = 1L; 
    @Transient private String uid; 
    @FXIgnore 
    public String getUid() { 
     if (uid == null) { 
      uid = "" + securityContactId; 
     } 
     return uid; 
    } 

    public void setUid(String uid) { 
     this.uid = uid; 
    } 

    @Id 
    @GeneratedValue(strategy=GenerationType.AUTO) 
    @Column(name="securityContact_id") 
    private Long securityContactId; 

    @Column(name="security_id") 
    private String securityId; 

    @Column(name="create_date") 
    private String createDate; 

    @Column(name="create_user") 
    private String createUser; 

    @Column(name="modify_date") 
    private String modifyDate; 

    @Column(name="modify_user") 
    private String modifyUser; 

    //uni-directional many-to-one association to AgentContact 

    @ManyToOne 
    @JoinColumn(name="agent_id", referencedColumnName="contact_id") 
    private Contact agentContact; 

    //uni-directional many-to-one association to AuditContact 
    @ManyToOne 
    @JoinColumn(name="audit_id", referencedColumnName="contact_id") 
    private Contact auditContact; 

    public SecurityContact() { 
    } 
    @FXKeyColumn 
    public Long getSecurityContactId() { 
     return this.securityContactId; 
    } 

    public void setSecurityContactId(Long securityContactId) { 
     this.securityContactId = securityContactId; 
    } 

    public String getSecurityId() { 
     return this.securityId; 
    } 

    public void setSecurityId(String securityId) { 
     this.securityId = securityId; 
    } 

    public String getCreateDate() { 
     return this.createDate; 
    } 

    public void setCreateDate(String createDate) { 
     this.createDate = createDate; 
    } 

    public String getCreateUser() { 
     return this.createUser; 
    } 

    public void setCreateUser(String createUser) { 
     this.createUser = createUser; 
    } 

    public String getModifyDate() { 
     return this.modifyDate; 
    } 

    public void setModifyDate(String modifyDate) { 
     this.modifyDate = modifyDate; 
    } 

    public String getModifyUser() { 
     return this.modifyUser; 
    } 

    public void setModifyUser(String modifyUser) { 
     this.modifyUser = modifyUser; 
    } 
    @FXManyToOne(parent="parent", property="contactId") 
    public Contact getAgentContact() { 
     return this.agentContact; 
    } 

    public void setAgentContact(Contact agentContact) { 
     this.agentContact = agentContact; 
    } 
    @FXManyToOne(parent="parent", property="contactId") 
    public Contact getAuditContact() { 
     return this.auditContact; 
    } 

    public void setAuditContact(Contact auditContact) { 
     this.auditContact = auditContact; 
    } 

} 

はHQL上記から生成されたSQLです。これを試してみてください:

SELECT sc 
FROM SecurityContact sc 
LEFT JOIN FETCH sc.agentContact 
LEFT JOIN FETCH sc.auditContact 
WHERE sc.securityId=:securityId2 
+0

何らかの理由で、Hibernateはクエリでannotated.xmlをビルドするときにエラーをスローします。 –

+0

どのようなエラー?どのバージョンのHibernate? –

+0

これは、基本的に、annotated.xmlファイルがビルドに失敗したことを伝えます。私はこれが、Hibernateがクエリについて気に入らないものがあるときに起こることを発見しました。私はバージョン3.4.0を使用しています。 –