LSe*_*rni 80 java generics hibernate
我是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();
}
}
Run Code Online (Sandbox Code Playgroud)
我想摆脱它SuppressWarnings
.但如果我这样做,我会收到警告
Warning: Unchecked cast from List to List<Foo>
Run Code Online (Sandbox Code Playgroud)
(我可以忽略它,但我想首先得不到它),如果我删除泛型以符合.list()
返回类型,我会收到警告
Warning: List is a raw type. References to generic type List<E>
should be parameterized.
Run Code Online (Sandbox Code Playgroud)
我注意到它org.hibernate.mapping
确实声明了一个List
; 但它完全是一种不同的类型 - Query
返回a java.util.List
,作为原始类型.我觉得很奇怪,最近的Hibernate(4.0.x)不会实现参数化类型,所以我怀疑是我做错了.
它看起来非常像Cast Hibernate结果到一个对象列表,但在这里我没有"硬"错误(系统知道类型Foo,我不是使用SQLQuery而是直接查询).所以没有快乐.
我也看过Hibernate Class Cast Exception,因为它看起来很有前途,但后来我意识到我实际上并没有得到任何Exception
...我的问题只是一个警告 - 一种编码风格,如果你愿意的话.
在jboss.org文件,休眠手册和几个教程似乎并不涵盖的话题这样的细节(或者我没有在正确的地方进行搜索?).当他们确实进入细节时,他们会使用即时投射 - 这是在官方jboss.org网站上没有的教程,所以我有点谨慎.
代码一经编译就没有明显的问题......我知道...... 结果是预期的结果.
那么:我这样做对吗?我错过了一些明显的东西吗 有"官方"或"推荐"的方式吗?
Bor*_*der 95
简短的回答@SuppressWarnings
是正确的方法.
答案很长,Hibernate List
从Query.list
方法返回一个raw ,见这里.这不是Hibernate的错误或可以解决的问题,查询返回的类型在编译时是未知的.
因此当你写作
final List<MyObject> list = query.list();
Run Code Online (Sandbox Code Playgroud)
你是从做不安全投List
来List<MyObject>
-这是无法避免的.
你无法安全地进行施法,因为它List
可以包含任何东西.
让错误消失的唯一方法就是更难看
final List<MyObject> list = new LinkedList<>();
for(final Object o : query.list()) {
list.add((MyObject)o);
}
Run Code Online (Sandbox Code Playgroud)
Tau*_*hts 22
解决方案是使用TypedQuery.从EntityManager创建查询时,请调用它:
TypedQuery<[YourClass]> query = entityManager.createQuery("[your sql]", [YourClass].class);
List<[YourClass]> list = query.getResultList(); //no type warning
Run Code Online (Sandbox Code Playgroud)
对于命名查询,本机命名查询等,这也是相同的.相应的方法与返回vanilla查询的方法具有相同的名称.只要知道返回类型,就可以使用它而不是Query.
您可以使用类似这样的解决方法来避免编译器警告:
List<?> resultRaw = query.list();
List<MyObj> result = new ArrayList<MyObj>(resultRaw.size());
for (Object o : resultRaw) {
result.add((MyObj) o);
}
Run Code Online (Sandbox Code Playgroud)
但是这段代码存在一些问题:
差别只是装饰性的,所以使用这样的解决方法 - 在我看来 - 毫无意义.
你必须忍受这些警告或抑制它们.
小智 6
要回答您的问题,没有“正确的方法”可以做到这一点。现在,如果它只是困扰您的警告,那么避免其扩散的最佳方法是将该Query.list()
方法包装到 DAO 中:
public class MyDAO {
@SuppressWarnings("unchecked")
public static <T> List<T> list(Query q){
return q.list();
}
}
Run Code Online (Sandbox Code Playgroud)
这样你就只能使用@SuppressWarnings("unchecked")
一次。
归档时间: |
|
查看次数: |
106912 次 |
最近记录: |