108

例如我有这样的查询:

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();

有没有办法避免它?

4

15 回答 15

101

正如建议的那样,在任何地方使用@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()您可以为等添加类似的方法。
于 2008-09-23T03:38:11.490 回答
43

自从提出问题以来已经有很长时间了,但我希望我的回答可能对像我这样的人有所帮助。

如果您查看 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();

你都准备好了。

于 2015-05-15T20:24:00.280 回答
21

我们@SuppressWarnings("unchecked")也使用它,但我们最常尝试仅在变量的声明中使用它,而不是在整个方法上使用它:

public List<Cat> findAll() {
    Query q = sess.createQuery("from Cat cat");
    @SuppressWarnings("unchecked")
    List<Cat> cats = q.list();
    return cats;
}
于 2008-09-22T16:55:18.523 回答
16

尝试使用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();
于 2016-04-05T11:02:14.303 回答
5

在我们的代码中,我们用以下方式注释调用方法:

@SuppressWarnings("未选中")

我知道这似乎是一种 hack,但一位联合开发人员最近检查并发现这是我们所能做的。

于 2008-09-22T15:57:42.733 回答
5

显然,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

于 2012-12-05T17:46:44.297 回答
4

这不是疏忽或错误。该警告反映了一个真正的潜在问题 - java 编译器无法真正确定 hibernate 类将正确地完成它的工作,并且它返回的列表将只包含 Cats。这里的任何建议都很好。

于 2009-02-13T02:55:37.613 回答
2

不,但您可以将其隔离到特定的查询方法中并使用@SuppressWarnings("unchecked")注释抑制警告。

于 2008-09-22T15:58:50.297 回答
2

较新版本的 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();
}
于 2018-02-10T05:53:31.487 回答
1

我们有同样的问题。但这对我们来说没什么大不了的,因为我们必须用 Hibernate Query 和 Session 解决其他更重要的问题。

具体来说:

  1. 控制何时可以提交事务。(我们想计算一个 tx 被“启动”了多少次,并且只有在 tx “结束”时才提交与它启动的次数相同的次数。对于不知道是否需要启动事务的代码很有用。现在任何需要 tx 的代码都只是“开始”一个并在完成后结束。)
  2. 性能指标收集。
  3. 延迟开始事务,直到知道某些事情实际上会完成。
  4. query.uniqueResult() 的行为更温和

所以对我们来说,我们有:

  1. 创建一个扩展 Query 的接口 (AmplafiQuery)
  2. 创建一个扩展 AmplafiQuery 并包装 org.hibernate.Query 的类 (AmplafiQueryImpl)
  3. 创建一个返回 Tx 的 Txmanager。
  4. Tx 有各种 createQuery 方法并返回 AmplafiQueryImpl

最后,

AmplafiQuery 有一个“asList()”,它是 Query.list() 的通用启用版本 AmplafiQuery 有一个“unique()”,它是 Query.uniqueResult() 的通用启用版本(并且只记录问题而不是抛出例外)

为了避免@SuppressWarnings,这需要做很多工作。但是,就像我说的(并列出)还有很多其他更好的!做包装工作的理由。

于 2009-02-13T02:08:02.673 回答
0

我知道这是较旧的,但截至今天,在 Matt Quails Answer 中需要注意 2 点。

第 1 点

List<Cat> cats = Collections.checkedList(Cat.class, q.list());

应该是这个

List<Cat> cats = Collections.checkedList(q.list(), Cat.class);

第 2 点

由此

List list = q.list();

对此

List<T> list = q.list();

会明显减少原始回复标签标记中的其他警告被浏览器剥离。

于 2012-04-01T22:53:29.057 回答
-1

试试这个:

Query q = sess.createQuery("from Cat cat");
List<?> results = q.list();
for (Object obj : results) {
    Cat cat = (Cat) obj;
}
于 2014-07-15T21:53:05.643 回答
-1

使用休眠查询避免类型安全警告的一个很好的解决方案是使用像TorpedoQuery这样的工具来帮助您构建类型安全的 hql。

Cat cat = from(Cat.class);
org.torpedoquery.jpa.Query<Entity> select = select(cat);
List<Cat> cats = select.list(entityManager);
于 2015-11-11T18:54:00.337 回答
-1
TypedQuery<EntityName> createQuery = entityManager.createQuery("from EntityName", EntityName.class);
List<EntityName> resultList = createQuery.getResultList();
于 2018-09-17T05:27:07.580 回答
-6

如果您不想使用 @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。

于 2008-09-22T16:34:04.643 回答