2013-04-24 234 views
7

儘管我的問題是關於Java泛型的,但我已經提供了一些與JPA相關的代碼來向您展示真實的上下文。Java泛型:如何從一個方法獲得泛型類型?

我正在使用JPA 2.0和基於Criteria API的查詢。我所有的查詢都遵循相同的模式(比較簡單的屬性;不需要路徑導航),所以我試圖編寫一個泛型類來處理JPA,同時保持業務邏輯處於分離的類中。我的目標是有一個方法,給定一個實體類型和一個存儲定義條件的對(字段名 - >期望值)的Map,返回一個bean(或bean的集合),其中一些實體字段的值。

我的所有實體都實現了Persistible接口,而我的所有傳輸對象都繼承自QueryBean。我認爲這些類與問題無關,所以我跳過了他們的代碼。

下面的代碼是我的第一種方法的一個片段(請假設CB是一個有效的CriteriaBuilder實例):

protected <T extends QueryBean, TT extends Persistible> Collection<T> executeQueryEntity 
     (Class<T> type, Class<TT> rootType, QueryConfig queryConfig, Map<String, Object> parameters) { 
    // (...) Initialization goes here 

    CriteriaQuery<T> c = cb.createQuery(type); 

    // FROM CLAUSE 
    Root<TT> root = c.from(rootType); 

    // SELECT CLAUSE 
    List<String> constructorParams = queryConfig.getTargetAttributes(); 
    Selection<?>[] selectArray = new Selection<?>[constructorParams.size()]; 
    for (int i = 0; i < constructorParams.size(); i++) { 
     selectArray[i] = root.get(constructorParams.get(i)); 
    } 
    c.select(cb.construct(type, selectArray)); 

    // WHERE CLAUSE 
    for (String filter : parameters.keySet()) { 
     if (queryConfig.getFieldConfiguration().get(filter).compareUsingEquals()) { 
      // SOME PREDICATE 
     } 
     else { 
      // SOME OTHER PREDICATE 
     } 
    } 

    // (...) Rest of the code goes here 
} 

我QueryConfig界面如下:

public interface QueryConfig { 

List<String> getTargetAttributes(); 
Map<String, FieldConfiguration> getFieldConfiguration(); 

} 

由於我已經使用提供關於查詢的信息的類(例如QueryBean構造函數所需的參數或關於實體字段的信息)的類,我認爲從該類獲取實體類型而不是將其作爲Cla類傳遞將會很不錯ss參數。我從this問題,它不能直接進行推斷,所以我嘗試以下解決方法:

添加一個方法來QueryConfig這樣的:

Class< ? extends Persistible> getTargetEntity(); 

增加一箇中間的方法是這樣的:

public <T extends QueryBean> Collection<T> queryMany(Class<T> type, QueryConfig config, Map<String, Object> parameters) { 
    executeQueryEntity(type, config.getTargetEntity(), parameters); 
} 

但它不會編譯。我相信原因在這裏解釋:Type mismatch for Class Generics但我其實不明白答案。 我的問題是:有沒有辦法避免將Class< TT >參數傳遞給execute方法?這是處理這個問題的好方法,還是我應該重構整個事情? 代碼的任何改進也是受歡迎的!

+1

你的英語,順便說一句,其實是很不錯的。實際上,除非你指出,否則我甚至都沒有注意到。 – Zyerah 2013-04-24 04:01:40

+2

@Telthien謝謝你,我盡我所能=) – DiegoAlfonso 2013-04-24 04:20:01

+1

你最好的傳球比許多母語人士更好!努力是真正的讚賞。 – Zyerah 2013-04-24 04:23:24

回答

2

我不太明白爲什麼你認爲你的方法將工作的原因: QueryConfigClass< ? extends Persistible> getTargetEntity();給可以通過編譯器被稱爲無類型信息,以及爲什麼你認爲編譯器可以「猜」你是類型將要返回,併爲您進行類型檢查?你可以做

一種方法是在QueryConfig

public interface QueryConfig <T extends Persistable> { 
    Class<T> getTargetEntity(); 
    List<String> getTargetAttributes(); 
    Map<String, FieldConfiguration> getFieldConfiguration(); 
} 

和你queryMany方法提供類型信息可以像:

public <T extends QueryBean, TT extends Persistible> 
Collection<T> queryMany(Class<T> type, 
         QueryConfig<TT> config, 
         Map<String, Object> parameters) { 
    executeQueryEntity(type, config.getTargetEntity(), parameters); 
} 
+0

非常感謝!我在嘗試類似的東西,但是在queryMany的簽名中遺漏了QueryConfig的類型參數,所以編譯器抱怨從Class轉換到Class DiegoAlfonso 2013-04-24 12:46:57