将 Hibernate Query.list() 转换为 List<Type> 的“正确”方法是什么?

新手上路,请多包涵

我是 Hibernate 的新手,我正在编写一个简单的方法来返回与特定过滤器匹配的对象列表。 List<Foo> 似乎是自然返回类型。

无论我做什么,我似乎都无法让编译器满意,除非我使用丑陋的 @SuppressWarnings

 import java.util.List;
import org.hibernate.Query;
import org.hibernate.Session;

public class Foo {

    public Session acquireSession() {
        // All DB opening, connection etc. removed,
        // since the problem is in compilation, not at runtime.
        return null;
    }

    @SuppressWarnings("unchecked") /* <----- */

    public List<Foo> activeObjects() {
        Session s = acquireSession();
        Query   q = s.createQuery("from foo where active");
        return (List<Foo>) q.list();
    }
}

我想摆脱那个 SuppressWarnings 。但如果我这样做,我会收到警告

Warning: Unchecked cast from List to List<Foo>

(我可以忽略它,但我不想一开始就得到它),如果我删除泛型以符合 .list() 返回类型,我会收到警告

Warning: List is a raw type. References to generic type List<E>
should be parameterized.

我注意到 org.hibernate.mapping 确实 声明了 List ;但它是完全不同的类型 - Query 返回一个 java.util.List 作为原始类型。我发现最近的 Hibernate (4.0.x) 没有实现参数化类型很奇怪,所以我怀疑是我做错了什么。

它看起来非常像 将 Hibernate 结果转换为对象列表,但在这里我没有出现“硬”错误(系统知道类型 Foo,而且我没有使用 SQLQuery,而是直接查询)。所以没有快乐。

我也看过 Hibernate Class Cast Exception ,因为它看起来很有希望,但后来我意识到我实际上 没有 得到任何 Exception …我的问题只是一个警告 - 一种编码风格,如果你将要。

jboss.org 上的文档、Hibernate 手册和一些教程似乎没有 如此 详细地涵盖该主题(或者我没有在正确的地方搜索?)。当他们确实进入细节时,他们会使用即时转换——而且这是在官方 jboss.org 网站上没有的教程中,所以我有点谨慎。

代码,一旦编译,运行没有 明显 的问题……我知道……但是;结果是预期的。

所以:我这样做对吗?我错过了一些明显的东西吗?是否有“官方”或“推荐” _的方式来做到这一点_?

原文由 LSerni 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 848
2 个回答

简短的回答 @SuppressWarnings 是正确的方法。

长答案,Hibernate 从 Query.list 方法返回原始 List 方法,请参见 此处。这不是 Hibernate 的错误或可以解决的问题,查询返回的类型在编译时 _未知_。

因此当你写

final List<MyObject> list = query.list();

您正在进行从 ListList<MyObject> 的不安全转换 - 这是无法避免的。

您无法安全地执行转换,因为 List 可能 包含任何内容。

使错误消失的唯一方法是更加丑陋

final List<MyObject> list = new LinkedList<>();
for(final Object o : query.list()) {
    list.add((MyObject)o);
}

原文由 Boris the Spider 发布,翻译遵循 CC BY-SA 3.0 许可协议

解决方案是改为使用 TypedQuery。从 EntityManager 创建查询时,改为像这样调用它:

 TypedQuery<[YourClass]> query = entityManager.createQuery("[your sql]", [YourClass].class);
List<[YourClass]> list = query.getResultList(); //no type warning

这也适用于命名查询、本机命名查询等。相应的方法与返回普通查询的方法具有相同的名称。每当您知道返回类型时,只需使用它而不是查询。

原文由 Taugenichts 发布,翻译遵循 CC BY-SA 3.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题