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

java - 将Hibernate Query.list()强制转换为List 的“正确”方法是什么?

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

无论我做什么,我似乎都无法让编译器高兴,除非我使用了一个丑陋的Exception。

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 activeObjects() {

Session s = acquireSession();

Query q = s.createQuery("from foo where active");

return (List) q.list();

}

}

我想摆脱Exception.但如果我这样做,我会收到警告

Warning: Unchecked cast from List to List

(我可以忽略它,但我想首先得不到它),如果我删除通用符合Exception返回类型,我收到警告

Warning: List is a raw type. References to generic type List

should be parameterized.

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

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

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

关于jboss.org,Hibernate手册和几个教程的文档似乎没有详细介绍这个主题(或者我没有在正确的位置搜索?)。 当他们确实进入细节时,他们会使用即时投射 - 这是在官方jboss.org网站上没有的教程,所以我有点谨慎。

代码一经编译就没有明显的问题......我知道...... 结果是预期的结果。

那么:我这样做对吗? 我错过了一些明显的东西吗 有没有“官方”或“推荐”的方式吗?

9个解决方案

92 votes

简短的回答List是正确的方法。

答案很长,Hibernate从List方法返回原始List,请看这里。 这不是Hibernate的错误或可以解决的问题,查询返回的类型在编译时是未知的。

因此当你写作

final List list = query.list();

你正在做一个不安全的演员,从List到List - 这是无法避免的。

由于List可能包含任何内容,因此无法安全地执行演员表。

让错误消失的唯一方法就是更难看

final List list = new LinkedList<>();

for(final Object o : query.list()) {

list.add((MyObject)o);

}

Boris the Spider answered 2019-05-17T06:57:05Z

14 votes

解决方案是使用TypedQuery。 从EntityManager创建查询时,请调用它:

TypedQuery query = entityManager.createQuery("[your sql]", [YourClass].class);

List list = query.getResultList(); //no type warning

对于命名查询,本机命名查询等,这也是相同的。相应的方法与返回vanilla查询的方法具有相同的名称。 只要知道返回类型,就可以使用它而不是Query。

Taugenichts answered 2019-05-17T06:57:38Z

6 votes

您可以使用类似这样的解决方法来避免编译器警告:

List> resultRaw = query.list();

List result = new ArrayList(resultRaw.size());

for (Object o : resultRaw) {

result.add((MyObj) o);

}

但是这段代码存在一些问题:

创建了多余的ArrayList

对查询返回的所有元素进行不必要的循环

更长的代码。

差别只是装饰性的,所以使用这样的解决方法 - 在我看来 - 毫无意义。

你必须忍受这些警告或抑制它们。

Grzegorz Olszewski answered 2019-05-17T06:58:45Z

2 votes

要回答你的问题,没有“正确的方法”来做到这一点。现在,如果它只是困扰你的警告,避免其扩散的最好方法是将@SuppressWarnings("unchecked")方法包装到DAO中:

public class MyDAO {

@SuppressWarnings("unchecked")

public static List list(Query q){

return q.list();

}

}

这样你只能使用@SuppressWarnings("unchecked")一次。

Pdv answered 2019-05-17T06:59:19Z

2 votes

List list = new ArrayList();

Criteria criteria = this.getSessionFactory().getCurrentSession().createCriteria(Person.class);

for (final Object o : criteria.list()) {

list.add((Person) o);

}

user3184564 answered 2019-05-17T06:59:40Z

1 votes

你使用这样的ResultTransformer:

public List activeObjects() {

Session s = acquireSession();

Query q = s.createQuery("from foo where active");

q.setResultTransformer(Transformers.aliasToBean(Foo.class));

return (List) q.list();

}

lakreqta answered 2019-05-17T07:00:08Z

1 votes

对我来说唯一有效的方法就是迭代器。

Iterator iterator= query.list().iterator();

Destination dest;

ArrayList destinations= new ArrayList<>();

Iterator iterator= query.list().iterator();

while(iterator.hasNext()){

Object[] tuple= (Object[]) iterator.next();

dest= new Destination();

dest.setId((String)tuple[0]);

dest.setName((String)tuple[1]);

dest.setLat((String)tuple[2]);

dest.setLng((String)tuple[3]);

destinations.add(dest);

}

通过我发现的其他方法,我遇到了问题

Popa Andrei answered 2019-05-17T07:00:50Z

0 votes

正确的方法是使用Hibernate Transformers:

public class StudentDTO {

private String studentName;

private String courseDescription;

public StudentDTO() { }

...

}

List resultWithAliasedBean = s.createSQLQuery(

"SELECT st.name as studentName, co.description as courseDescription " +

"FROM Enrolment e " +

"INNER JOIN Student st on e.studentId=st.studentId " +

"INNER JOIN Course co on e.courseCode=co.courseCode")

.setResultTransformer( Transformers.aliasToBean(StudentDTO.class))

.list();

StudentDTO dto =(StudentDTO) resultWithAliasedBean.get(0);

迭代通过Object []是多余的,会有一些性能损失。有关变压器使用的详细信息,请访问:用于HQL和SQL的变换器

如果您正在寻找更简单的解决方案,您可以使用开箱即用的地图变换器:

List iter = s.createQuery(

"select e.student.name as studentName," +

" e.course.description as courseDescription" +

"from Enrolment as e")

.setResultTransformer( Transformers.ALIAS_TO_ENTITY_MAP )

.iterate();

String name = (Map)(iter.next()).get("studentName");

ANTARA answered 2019-05-17T07:01:37Z

-1 votes

我在这里找到了最好的解决方案,这个问题的关键是addEntity方法

public static void testSimpleSQL() {

final Session session = sessionFactory.openSession();

SQLQuery q = session.createSQLQuery("select * from ENTITY");

q.addEntity(Entity.class);

List entities = q.list();

for (Entity entity : entities) {

System.out.println(entity);

}

}

Federico Traiman answered 2019-05-17T07:02:08Z

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值