2013-02-01 28 views
0

當我涉及到Hibernate時,我相對比較綠色,但是我面臨着調試看起來應該起作用的Criteria查詢。休眠子查詢.notIn錯誤地排除結果

的數據結構大致如下:

User { Integer id, String type, String email, List<CustomerPolicy> policies, .... } 
CustomerPolicy { List<PolicyTable> tables, ... } 
PolicyTable { List<Insured> insureds, ... } 
Insured { Applicant applicant, ... } 
Applicant { String email, ... } 

我試圖讓電子郵件列表上的所有申請人的上一個用戶的連接CustomerPolicies,除了對於那些符合那些現有的在電子郵件用戶表。

這裏是我們的代碼查詢,不工作:

 

    emails.addAll(User.createCriteria().list() { 
     eq("id", id) 
     eq("type", "A") 
     createAlias("policies", "policy") 
     createAlias("policy.tables", "table") 
     createAlias("table.insureds", "insured") 
     createAlias("insured.applicant", "applicant") 
     isNotNull("applicant.email") 
     add(Subqueries.propertyNotIn("applicant.email", emailSubquery)) 
     projections { 
      distinct("applicant.email") 
     } 
    }) 

    emailSubquery = DetachedCriteria.forClass(User).setProjection(Projections.property("email")) 

我有大約4政策,每3-5個左右的表,均與至少一個與申請人投保用戶,大約一半的申請人在用戶表([email protected])中有的電子郵件,另一半在用戶表([email protected])中有不是的電子郵件。

隨着emailSubquery的到位,沒有任何電子郵件正在返回。刪除子查詢後,兩者都返回。我已驗證[email protected]絕對不在用戶表中。

這個查詢有什麼問題?

+0

看起來像一個子查詢沒有延遲初始化。 –

+0

愛麗絲,有沒有可能在列表操作之前未定義emailSubquery?在你的例子中,它是在列表操作之後定義的。它有可能是之前定義的其他東西嗎? –

+0

emailSubquery實際上是一個方法調用,所以它嚴格來說不是預定義的。我剛剛在emails.addAll之前立即將它分配給一個變量,並且我仍然收到0封電子郵件。 –

回答

0

我假設您正在使用Oracle進行此查詢,並且這是行爲怪異來自的地方。

本質上,Oracle爲其SQL執行提供了一個優化編譯器。 「不在」與「不存在」vs「左連接」的詳細信息在this article中有詳細介紹。

爲了解決這個問題,使用propertyNotIn方法沒有看到任何結果的原因是,您的「用戶」表上的email屬性包含空對象。以下是an example,它爲您提供的模式舉例說明了這種行爲。

更合適,你會想要做的是使用Subqueries.notExists方法生產出here這樣就可以得到結果,即使有該列空值的查詢結果。

最良好的祝願,希望這有助於。

HT:SQL "select where not in subquery" returns no results

+0

我遇到過那種惱人的空對象問題,但忘了在這裏考慮。我更新了分離標準以消除上述建議的空值並解決了問題。謝謝! –