2016-11-10 137 views
1

我想爲返回結果的JSE應用程序創建JPA事務。如何指定泛型類型作爲函數參數

@SuppressWarnings("unchecked") 
public static <T> T transaction(EmWorker worker, Class<T>clazz){ 

    EntityManager em = createEntityManager(); 
    em.getTransaction().begin(); 

    // >>> My Functional interface 
    Object result = worker.work(em); 

    em.getTransaction().commit(); 
    em.close(); 
    return (T)result; 
} 

它適用於讀取單個對象:

FunkoPop gandalf=EmFactory.transaction( eManager -> { 
    return eManager.find(FunkoPop.class, 1); 
}, FunkoPop.class); 

但現在,我想的FunkoPop一個List

List<FunkoPop> list =EmFactory.transaction( e -> { 

    String query = "SELECT f FROM FunkoPop f "; 
    List<FunkoPop> l = e.createQuery(query, FunkoPop.class).getResultList(); 
    return l; 

}, List<FunkoPop>.class); //Won't compile ; or List.class gives warnings 

transaction需要兩個參數:lambda和class。我近似理解,我無法捕獲類型List<FunkoPop>.class,因爲此參數將丟失通用的<FunkoPop>。什麼是沒有警告的解決方案?

+1

你應該使用'clazz.cast(結果)'而非'(T)result'。然後,你不需要'@SuppressWarnings(「unchecked」)'。不過,這隻適用於可授權類型,不適用於'List '。但是什麼是EmWorker?製作該類型的泛型(或者用Function '替換它)將消除所有這些特技的需求。 – Holger

回答

1

你不能因爲沒有List<FunkoPop>類型。全部有List

您可以但是做硬盤的方式:

List<T> transaction(EmWorker worker, Class<T>clazz) { 
    ... 
    List<T> l = (List<T>)e.createQuery(query, clazz).getResultList(); 
    return l; 
} 

您可能需要重命名的方法。

1

添加第二個功能界面產生列表:

public static interface EmListWorker<T> { 
    public List<T> work(EntityManager em); 
} 

public static <T> List<T> transaction(EmListWorker<T> worker, Class<T>clazz){ 
    EntityManager em = createEntityManager(); 
    em.getTransaction().begin(); 

    // >>> alternative Functional interface 
    List<T> result = worker.work(em); 

    em.getTransaction().commit(); 
    em.close(); 
    return result; 
} 
+2

或者僅從一開始就使用'Function '並且移除現在已過時的'Class '參數。這適用於*每個*類型。 – Holger

0

使用@Holger提到的是偉大的Function<EntityManager, T>。實現起來要簡單得多:沒有功能接口,也沒有髒話。並且它返回一個檢查類型。

實現:

public static <T> T transaction(Function<EntityManager,T> worker){ 

    EntityManager em = createEntityManager(); 
    em.getTransaction().begin(); 

    T result = worker.apply(em); 

    em.getTransaction().commit(); 
    em.close(); 

    return result; 
} 

用法:

FunkoPop gandalf = new FunkoPop("Gandalf"); 

    EmFactory.transaction(em -> { 
     em.persist(gandalf); 
     return gandalf; 
    }); 

    List<FunkoPop> list =EmFactory.transaction(em -> { 
     String query = "SELECT f FROM FunkoPop f "; 
     return em.createQuery(query, FunkoPop.class).getResultList(); 
    }); 
相關問題