如何在Hibernate HQL结果中避免类型安全警告?

时间:2020-03-06 14:32:50  来源:igfitidea点击:

例如我有这样的查询:

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。这里的任何建议都可以。