例如我有这样的查询:
Query q = sess.createQuery("from Cat cat");
List cats = q.list();
如果我尝试做这样的事情,它会显示以下警告
Type safety: The expression of type List needs unchecked conversion to conform to List<Cat>
List<Cat> cats = q.list();
有没有办法避免它?
正如建议的那样,在任何地方使用@SuppressWarnings
是一种很好的方法,尽管每次调用时确实需要一些手指打字q.list()
。
我建议还有另外两种技术:
写一个演员表助手
只需将所有内容重构@SuppressWarnings
到一个地方:
List<Cat> cats = MyHibernateUtils.listAndCast(q);
...
public static <T> List<T> listAndCast(Query q) {
@SuppressWarnings("unchecked")
List list = q.list();
return list;
}
防止 Eclipse 为不可避免的问题生成警告
在 Eclipse 中,转到 Window>Preferences>Java>Compiler>Errors/Warnings 并在 Generic 类型下,选中复选框
Ignore unavoidable generic type problems due to raw APIs
这将关闭针对类似问题的不必要警告,例如上述不可避免的问题。
一些评论:
Query
而不是结果,q.list()
因为这样这种“作弊”方法只能用于在 Hibernate 中作弊,而不是List
在一般情况下作弊。.iterate()
您可以为等添加类似的方法。自从提出问题以来已经有很长时间了,但我希望我的回答可能对像我这样的人有所帮助。
如果您查看 javax.persistence api 文档,您会发现从那以后那里添加了一些新方法Java Persistence 2.0
。其中之一是createQuery(String, Class<T>)
返回TypedQuery<T>
。您可以TypedQuery
像以前一样使用它,但Query
现在所有操作都是类型安全的。
因此,只需将您的代码更改为如下所示:
Query q = sess.createQuery("from Cat cat", Cat.class);
List<Cat> cats = q.list();
你都准备好了。
我们@SuppressWarnings("unchecked")
也使用它,但我们最常尝试仅在变量的声明中使用它,而不是在整个方法上使用它:
public List<Cat> findAll() {
Query q = sess.createQuery("from Cat cat");
@SuppressWarnings("unchecked")
List<Cat> cats = q.list();
return cats;
}
尝试使用TypedQuery
而不是Query
. 例如,而不是这个: -
Query q = sess.createQuery("from Cat cat", Cat.class);
List<Cat> cats = q.list();
用这个:-
TypedQuery<Cat> q1 = sess.createQuery("from Cat cat", Cat.class);
List<Cat> cats = q1.list();
在我们的代码中,我们用以下方式注释调用方法:
@SuppressWarnings("未选中")
我知道这似乎是一种 hack,但一位联合开发人员最近检查并发现这是我们所能做的。
显然,Hibernate API 中的 Query.list() 方法“设计”不是类型安全的,并且没有计划对其进行更改。
我相信避免编译器警告的最简单的解决方案确实是添加@SuppressWarnings("unchecked")。这个注解可以放在方法级别,或者,如果在方法内部,可以放在变量声明之前。
如果您有一个封装 Query.list() 并返回 List(或 Collection)的方法,您也会收到警告。但是这个是使用@SuppressWarnings("rawtypes") 抑制的。
Matt Quail 提出的 listAndCast(Query) 方法不如 Query.list() 灵活。虽然我可以做到:
Query q = sess.createQuery("from Cat cat");
ArrayList cats = q.list();
如果我尝试下面的代码:
Query q = sess.createQuery("from Cat cat");
ArrayList<Cat> cats = MyHibernateUtils.listAndCast(q);
我会得到一个编译错误:类型不匹配:无法从 List 转换为 ArrayList
这不是疏忽或错误。该警告反映了一个真正的潜在问题 - java 编译器无法真正确定 hibernate 类将正确地完成它的工作,并且它返回的列表将只包含 Cats。这里的任何建议都很好。
不,但您可以将其隔离到特定的查询方法中并使用@SuppressWarnings("unchecked")
注释抑制警告。
较新版本的 Hibernate 现在支持类型安全Query<T>
对象,因此您不再需要使用@SuppressWarnings
或实现一些技巧来消除编译器警告。在Session API中,Session.createQuery
现在将返回一个类型安全的Query<T>
对象。你可以这样使用它:
Query<Cat> query = session.createQuery("FROM Cat", Cat.class);
List<Cat> cats = query.list();
您也可以在查询结果不返回 Cat 时使用它:
public Integer count() {
Query<Integer> query = sessionFactory.getCurrentSession().createQuery("SELECT COUNT(id) FROM Cat", Integer.class);
return query.getSingleResult();
}
或者在进行部分选择时:
public List<Object[]> String getName() {
Query<Object[]> query = sessionFactory.getCurrentSession().createQuery("SELECT id, name FROM Cat", Object[].class);
return query.list();
}
我们有同样的问题。但这对我们来说没什么大不了的,因为我们必须用 Hibernate Query 和 Session 解决其他更重要的问题。
具体来说:
所以对我们来说,我们有:
最后,
AmplafiQuery 有一个“asList()”,它是 Query.list() 的通用启用版本 AmplafiQuery 有一个“unique()”,它是 Query.uniqueResult() 的通用启用版本(并且只记录问题而不是抛出例外)
为了避免@SuppressWarnings,这需要做很多工作。但是,就像我说的(并列出)还有很多其他更好的!做包装工作的理由。
我知道这是较旧的,但截至今天,在 Matt Quails Answer 中需要注意 2 点。
这
List<Cat> cats = Collections.checkedList(Cat.class, q.list());
应该是这个
List<Cat> cats = Collections.checkedList(q.list(), Cat.class);
由此
List list = q.list();
对此
List<T> list = q.list();
会明显减少原始回复标签标记中的其他警告被浏览器剥离。
试试这个:
Query q = sess.createQuery("from Cat cat");
List<?> results = q.list();
for (Object obj : results) {
Cat cat = (Cat) obj;
}
使用休眠查询避免类型安全警告的一个很好的解决方案是使用像TorpedoQuery这样的工具来帮助您构建类型安全的 hql。
Cat cat = from(Cat.class);
org.torpedoquery.jpa.Query<Entity> select = select(cat);
List<Cat> cats = select.list(entityManager);
TypedQuery<EntityName> createQuery = entityManager.createQuery("from EntityName", EntityName.class);
List<EntityName> resultList = createQuery.getResultList();
如果您不想使用 @SuppressWarnings("unchecked") 您可以执行以下操作。
Query q = sess.createQuery("from Cat cat");
List<?> results =(List<?>) q.list();
List<Cat> cats = new ArrayList<Cat>();
for(Object result:results) {
Cat cat = (Cat) result;
cats.add(cat);
}
仅供参考 - 我创建了一个 util 方法来为我执行此操作,因此它不会乱扔我的代码,我也不必使用 @SupressWarning。