2009-06-12 127 views
5

我有兩個類Person和Company,派生自另一個類Contact。它們在兩個表格(Person和Company)中以多態表示。簡化類看起來是這樣的:Hibernate多態查詢

public abstract class Contact { 

    Integer id; 

    public abstract String getDisplayName(); 

} 

public class Person extends Contact { 

    String firstName; 
    String lastName; 

    public String getDisplayName() { 
    return firstName + " " + lastName; 
    } 

} 

public class Company extends Contact { 

    String name; 

    public String getDisplayName() { 
    return name; 
    } 

} 

問題是,我需要查詢查找所有與displayName包含特定字符串的聯繫人。我無法使用displayName進行查詢,因爲它不是任何表的一部分。有關如何執行此查詢的任何想法?

+0

你能標記這個Java嗎? – 2009-06-12 13:56:19

回答

4

因爲您在Java類中進行了連接,所以Hibernate無法真正幫助您解決這個問題,對不起。它可能根本不會看到你在這個方法中做了什麼,因爲它實際上並不涉及持久性。

的解決方案取決於你如何映射到這些類的繼承:

如果是表每個層次結構,你可以使用這種方法:編寫一個SQL WHERE子句條件查詢,然後使用的情況下,聲明:

s.createCriteria(Contact.class) 
.add(Restrictions.sqlRestriction("? = case when type='Person' then firstName || ' '|| lastName else name end")) 
.list(); 

如果是表每個具體的子類,那麼你就寫兩個查詢(因爲這是Hibernate會做反正)的更好。

+0

我把它作爲每個具體類的表。也許最快的解決方案是編寫兩個查詢,並將它們組合在java端。 – rmarimon 2009-06-13 11:37:22

2

您可以在Contact表中創建一個新列,其中包含各自的displayName,您可以通過休眠Interceptor來填充該列,以便自動始終包含正確的字符串。

替代方案將有兩個查詢,一個用於Person,另一個用於Company表,每個查詢都包含各自的搜索邏輯。你可能不得不使用原生查詢來實現通過LIKE查詢來查找連接字符串(我不是HQL專家,儘管這很可能)。

如果你有大表,你應該考慮全文索引,因爲LIKE '%...%'查詢需要全表掃描,除非你的數據庫支持全文索引。

1

如果將displayName更改爲映射屬性(設置爲Company中的名稱列和公式中的第一個||''|| last中的Person),那麼可以查詢Contract和Hibernate將同時運行兩個查詢其中現在有一個displayName。你將得到一個兩個列表的列表,其中一個包含公司,一個包含人員,因此你必須將它們合併回去。我認爲你需要通過合同的完整包名來查詢,或者設置一個typedef來告訴Hibernate它。