虽然我的问题是关于 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 构造函数所需的参数或有关实体字段的信息),我认为从该类中获取实体类型而不是将其传递为一个类参数。我从这个问题推断它不能直接完成,所以我尝试了以下解决方法:
像这样向 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);
}
但它不会编译。我相信这里解释了原因:Type mismatch for Class Generics但我实际上不明白答案。我的问题是:有没有办法避免将Class< TT >
参数传递给执行方法?这是处理问题的好方法还是我应该重构整个事情?也欢迎对代码进行任何改进!