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

时间:2021-11-02 16:09:26

I want to create a JPA transaction for a JSE app that returns a result.

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

It works for fetching a single object :

它适用于获取单个对象:

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

But now, I want a List of FunkoPop.

但现在,我想要一个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

The transaction needs two arguments : a lambda and a class. I approximatively understand that I cannot capture the type List<FunkoPop>.class as this parameter will loose the <FunkoPop> generic. What would be the solution to have no warnings ?

该事务需要两个参数:lambda和class。我近似理解我无法捕获类型List .class,因为此参数将松散 泛型。什么是没有警告的解决方案?

3 个解决方案

#1


1  

you can't because there is no List<FunkoPop> type. All there is a List.

你不能,因为没有List 类型。所有都有一个清单。

You may however do it the hard way:

但是你可能会这么做:

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

You might need to rename the method.

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

#2


1  

Add a second functional interface to produce lists:

添加第二个功能接口以生成列表:

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

#3


0  

Using Function<EntityManager, T> mentioned by @Holger is great. It's much simpler to implement : no Function Interface and no dirty cast. And it returns a checked type.

使用@Holger提到的函数 很棒。实现起来要简单得多:没有函数接口,也没有脏转换。它返回一个检查类型。 ,t>

Implementation :

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

Usage :

    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();
    });

#1


1  

you can't because there is no List<FunkoPop> type. All there is a List.

你不能,因为没有List 类型。所有都有一个清单。

You may however do it the hard way:

但是你可能会这么做:

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

You might need to rename the method.

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

#2


1  

Add a second functional interface to produce lists:

添加第二个功能接口以生成列表:

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

#3


0  

Using Function<EntityManager, T> mentioned by @Holger is great. It's much simpler to implement : no Function Interface and no dirty cast. And it returns a checked type.

使用@Holger提到的函数 很棒。实现起来要简单得多:没有函数接口,也没有脏转换。它返回一个检查类型。 ,t>

Implementation :

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

Usage :

    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();
    });