2016-11-10 5 views
1

結果を返すJSEアプリケーション用のJPAトランザクションを作成したいとします。ジェネリック型を関数パラメータとして指定する方法

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

をしかし、今、私はFunkoPopListをしたい:

@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; 
} 

これは、単一のオブジェクトを取得するために動作します。ラムダとクラス:

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は2つの引数を必要とします。私は近似的に、タイプList<FunkoPop>.classをキャプチャすることができないことを理解しています。このパラメータは<FunkoPop>ジェネリックを失います。何の警告もない解決策はありますか?

+1

あなたは 'clazz.cast(結果)'の代わりに '(T)result'を使用する必要があります。それから '@SuppressWarnings("未チェック ")は必要ありません。それでも、それは 'List 'のためのものではなく、reifiable型のためだけに機能します。しかし、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

は、リストを生成するために、第二の機能のインタフェースを追加します。@Holger言及Function<EntityManager, T>を使用して

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

は素晴らしいです。実装するのがはるかに簡単です。関数インターフェイスがなく、ダーティーキャストはありません。チェックされた型を返します。

実装:

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(); 
    }); 
関連する問題