繁体   English   中英

Java泛型:如何从方法中获取泛型类型?

[英]Java generics: how to get a generic type from a method?

虽然我的问题是关于Java泛型,但我已经提出了一些与JPA相关的代码来向您展示真实的上下文。

我正在使用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();

}

由于我已经在使用QueryConfig类来提供有关查询的信息(例如QueryBean构造函数所需的参数或有关实体字段的信息),我认为从该类获取实体类型而不是传递它会很好作为Class参数。 我从这个问题推断它不能直接完成,所以我尝试了以下解决方法:

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

但它不会编译。 我相信原因在这里解释: Class Generics的类型不匹配但我实际上不理解答案。 我的问题是:有没有办法避免将Class< TT >参数传递给execute方法? 这是处理问题的好方法还是我应该重构整个问题? 对代码的任何改进也是受欢迎的!

我不太明白你认为你的方法会起作用的原因: QueryConfig with Class< ? extends Persistible> getTargetEntity(); Class< ? 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);
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM