2011-08-02 173 views
1

我有一個名爲SecurityContact的表,它與另一個表Contacts具有多對一的關係。它有兩個連接到聯繫人列,其中一個名爲agentContact和另一個auditContact。我試圖運行下面的HQL查詢:休眠忽略LEFT JOIN

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

當然,Hibernate完全忽略了LEFT JOIN語句,並繼續生成SQL利用內部連接。這根本不適合我的目的。我試圖設置抓取註釋,但沒有運氣。這個問題一直讓我瘋狂了兩天,所以任何幫助都會非常感激。

這裏是我的SecurityContact類的代碼:

/** 
* 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 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查詢回答什麼問題?你期望什麼結果不同於簡單的'from SecurityContact where securityId =?'? –

+0

@matt這很重要,因爲即使沒有相應的agentContact或auditContact可用,我也希望Hibernate返回條目。它不會通過內部連接來完成。 –

+0

但不是那些'@ ManyToOne'關聯可選/默認爲空?這種關係的反面在另一類中是什麼樣的?你是說一個簡單的'session.get(SecurityContact.class,securityId)'不會返回任何一個字段爲空的實例嗎? –

回答

1

我所做的關於您的問題的一些測試,在我看來,你必須有你的映射問題或休眠的(過時)版本你是一個錯誤使用。

對於可選@ManyToOne協會,休眠應該已經使用LEFT JOIN查詢實體和它的關聯(因爲它是查詢根實體相關聯的實體是否是空的唯一途徑)。

我扔了一個示例項目,在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; 

在單元測試中,有兩個測試的Employee.team參考is not-null when it is set in the DB,和另一個測試斷言Employee.teamis null when not set在數據庫表。

此外,CompanyEmployee實體之間存在類似的雙向關係,並具有類似的測試。

最後,在日誌中我可以看到,當Hibernate查詢的Employee實體(用一個簡單的session.get(Employee.class, id)),它採用了左湊teams表拉(我加換行符自己):

DEBUG org.hibernate.SQL - 選擇employee0_.id爲id1_2_,employee0_.company_id爲company6_1_2_,employee0_.dateOfBirth爲dateOfBi2_1_2_,employee0_.employmentStartDate爲employme3_1_2_,employee0_.firstName爲firstName1_2_,employee0_.lastName爲lastName1_2_,employee0_.team_id爲as team7_1_2_,company1_.id爲id0_0_,company1_.name爲name0_0_,team2_.id爲id2_1_,team2_.name爲name2_1_
from emp loyees employee0_
left outer join companies company1_ on employee0_.company_id = company1_.id
left outer join teams team2_ on employee0_.team_id = team2_.id where employee0_.id =?

因此,在總結,爲了讓Hibernate使用左您的相關實體之間的連接,只要關係設置爲可選,應該不需要特殊的HQL查詢都 - 一個簡單的session.get()對於根實體應該使用左連接來查詢關聯實體的表。如果您看到不同的結果,則表明您的Hibernate版本中存在一個錯誤(我在此處使用3.6.6.Final),或者在映射中存在不正確的錯誤。

1

HQL join syntax看起來靠不住的。試試這個:

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。 –