我要封装一个基于hibernate6的 查询函数,大概的需求是这样的,传入一个hql语句,返回List<Map<String,Object>>,完成的函数如下:
public List<Map> findMap(String hql, Object... values) throws Exception {
Query<Map> queryObject = getSession().createQuery(hql,Map.class);
if (values != null) {
for (int i = 1; i <= values.length; i++) {
if (values[i-1].getClass().isArray()) {
Object[] pas = (Object[]) values[i-1];
queryObject.setParameterList(i, pas);
} else {
queryObject.setParameter(i, values[i-1]);
}
}
}
queryObject.unwrap(Query.class).setTupleTransformer((tuple, aliases)->{
Map<String, Object> map=new HashMap<>();
map.put(aliases[0], tuple[0]);
return map;
});
return queryObject.list();
}
以上代码是可以运行的,但是两个警告:
1、Map is a raw type. References to generic type Map<K,V> should be parameterized
2、Type safety: The method setTupleTransformer(TupleTransformer) belongs to the raw type Query. References to generic type Query should be parameterized
请问在不使用注解 :@SuppressWarnings({ "rawtypes", "unchecked" })的情况下,如何优雅的消除这个警告
第一个警告是因为
Query<Map> queryObject = getSession().createQuery(hql,Map.class);
产生的,而下述代码也不完美
//hibernate6不建议使用这样的语句
Query<Map<String,Object>> queryObject = getSession().createQuery(hql);
//这样的代码编译出错
Query<Map<String,Object>> queryObject = getSession().createQuery(hql,Map.class);
第二个警告,个人估计也是因为queryObject.unwrap(Query.class)中的Query 没有指定类型导致的,毕竟原型是Query
queryObject.unwrap(Query.class).setTupleTransformer((tuple, aliases)->{
Map<String, Object> map=new HashMap<>();
map.put(aliases[0], tuple[0]);
return map;
});
参考GPT和自己的思路:
对于第一个警告,可以使用泛型来消除,将函数签名改为:
public List<Map<String, Object>> findMap(String hql, Object... values) throws Exception {
同时,需要将第2行的代码改为:
Query<Map<String, Object>> queryObject = getSession().createQuery(hql);
对于第二个警告,需要将第13行的代码改为:
queryObject.unwrap(org.hibernate.query.Query.class).setTupleTransformer((tuple, aliases)->{
使用完整的泛型类型,以及使用org.hibernate.query.Query
代替原来的Query
,可以消除警告。
如果将第2行的代码改为Query<Map<String,Object>> queryObject = getSession().createQuery(hql);
,则不需要使用元素转换器了,不需要第13-17行的代码。直接返回queryObject.list()
即可。
参考GPT和自己的思路:
针对第一个警告,可以在方法声明中使用泛型,将Map改为Map<String, Object>。修改后的代码如下:
public List<Map<String, Object>> findMap(String hql, Object... values) throws Exception {
Query<Map<String, Object>> queryObject = getSession().createQuery(hql, Map.class);
if (values != null) {
for (int i = 1; i <= values.length; i++) {
if (values[i-1].getClass().isArray()) {
Object[] pas = (Object[]) values[i-1];
queryObject.setParameterList(i, pas);
} else {
queryObject.setParameter(i, values[i-1]);
}
}
}
queryObject.unwrap(Query.class).setTupleTransformer((tuple, aliases) -> {
Map<String, Object> map = new HashMap<>();
map.put(aliases[0], tuple[0]);
return map;
});
return queryObject.list();
}
针对第二个警告,可以在createQuery方法中指定泛型参数,避免使用原始类型。修改后的第二个问题代码如下:
Query<Map<String, Object>> queryObject = getSession().createQuery(hql, Map.class);
参考GPT和自己的思路:
对于第一个警告:Map is a raw type. References to generic type Map<K,V> should be parameterized。建议改为声明Map<String,Object>。
改动后的代码如下所示:
public List<Map<String,Object>> findMap(String hql, Object... values) throws Exception {
Query<Map<String,Object>> queryObject = getSession().createQuery(hql,Map.class);
if (values != null) {
for (int i = 1; i <= values.length; i++) {
if (values[i-1].getClass().isArray()) {
Object[] pas = (Object[]) values[i-1];
queryObject.setParameterList(i, pas);
} else {
queryObject.setParameter(i, values[i-1]);
}
}
}
queryObject.unwrap(Query.class).setTupleTransformer((tuple, aliases)->{
Map<String, Object> map=new HashMap<>();
map.put(aliases[0], tuple[0]);
return map;
});
return queryObject.list();
}
对于第二个警告:Type safety: The method setTupleTransformer(TupleTransformer) belongs to the raw type Query. References to generic type Query should be parameterized。建议将setTupleTransformer的参数声明为TupleTransformer<Map<String, Object>>。
改动后的代码如下所示:
queryObject.unwrap(Query.class).setTupleTransformer((TupleTransformer<Map<String, Object>>) (tuple, aliases)->{
Map<String, Object> map=new HashMap<>();
map.put(aliases[0], tuple[0]);
return map;
});
对于第二个问题,如果使用泛型声明,可以直接写为:Query<Map<String,Object>>。
这是参数类型的警告,要匹配一致。
我知道要保证类型一致啊,问题是我咋写 才能保证一致啊