如何在Hibernate HQL结果中避免类型安全警告?
例如我有这样的查询:
Query q = sess.createQuery("from Cat cat"); List cats = q.list();
如果我尝试做这样的事情,它将显示警告"类型安全:List类型的表达式需要未经检查的转换才能符合List":
List<Cat> cats = q.list();
有办法避免吗?
解决方案
在我们的代码中,我们使用以下注释注释调用方法:
@SuppressWarnings("未选中")
我知道这看起来像是骇客,但一位共同开发人员最近检查了一下,发现这就是我们所能做的。
不可以,但是我们可以将其隔离为特定的查询方法,并使用" @SuppressWarnings(" unchecked"))批注来禁止显示警告。
如果我们不想使用@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。
Joe Dean的解决方案看起来很有趣,但是我们认为值得创建一个新的List并遍历所有元素以消除警告是值得的吗?
(对不起,由于某种原因无法在其解决方案中直接添加评论)
我们也使用@SuppressWarnings(" unchecked")
,但是我们经常尝试仅在变量的声明中使用它,而不是在整个方法中使用它:
public List<Cat> findAll() { Query q = sess.createQuery("from Cat cat"); @SuppressWarnings("unchecked") List<Cat> cats = q.list(); return cats; }
如建议的那样,在各处都使用@SuppressWarnings是一种很好的方法,尽管每次调用q.list()时确实要花一点手指。
我建议使用其他三种技术:
Collections.checkedList()
用以下内容替换作业:
List<Cat> cats = Collections.checkedList(q.list(), Cat.class);
我们可能要检查该方法的javadoc,尤其是关于equals和hashCode的情况。
写一个演员帮手
只需将所有@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中,转到"窗口">"首选项">" Java">"编译器">"错误/警告",然后在"通用类型"下,选中复选框
忽略由于原始API不可避免的泛型类型问题
对于类似的问题,这将关闭不必要的警告,这些警告是不可避免的。
一些评论:
- 我选择传递"查询"而不是" q.list()"的结果,因为那样,这种"欺骗"方法只能用于与Hibernate进行欺骗,而通常不能用于欺骗任何" List"。
- 我们可以为.iterate()等添加类似的方法。
我们有同样的问题。但这对我们来说并不重要,因为我们不得不使用Hibernate Query和Session解决其他更主要的问题。
具体来说:
- 控制何时可以提交事务。 (我们想计算tx被"启动"的次数,并且仅在tx被"终止"与启动相同的次数时才提交。对于不知道是否需要启动事务的代码很有用。现在任何需要发送代码的代码只会"开始"一个代码,并在完成后结束代码。)
- 绩效指标收集。
- 延迟启动事务,直到知道将实际完成某件事为止。
- query.uniqueResult()的行为更加温和
因此,对于我们来说,我们有:
- 创建扩展查询的接口(AmplafiQuery)
- 创建一个扩展AmplafiQuery并包装org.hibernate.Query的类(AmplafiQueryImpl)
- 创建一个返回Tx的Txmanager。
- Tx具有各种createQuery方法并返回AmplafiQueryImpl
最后,
AmplafiQuery具有一个" asList()",它是Query.list()的常规启用版本
AmplafiQuery具有一个" unique()",它是Query.uniqueResult()的常规启用版本(并且仅记录问题而不是引发异常)
避免@SuppressWarnings要做很多工作。但是,就像我说的(和列出的)一样,还有很多其他更好的选择!做包裹工作的原因。
这不是疏忽或者错误。该警告反映了一个真正的潜在问题,java编译器无法真正确定hibernate类将正确执行其工作,并且返回的列表仅包含Cats。这里的任何建议都可以。