如何将Generic Type指定为函数参数

时间:2016-11-10 12:38:27

标签: java generics jpa java-8

我想为返回结果的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);

但现在,我想要一个List FunkoPop

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>泛型。什么是没有警告的解决方案?

3 个答案:

答案 0 :(得分: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 :(得分: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 :(得分: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();
    });