Query#list() returns a list of object arrays. Each field of the array contains one of the selected properties.select c.name, c.order from Customer c
In my opinion iterating over lists of
Object[] is verbose and error-prone because processing the result-list is directly dependant on the sequence of selected properties in the hql string. If you change the query string you have to change the sourcecode as well.Did I mention how expressive HQL is? :) Check out the following snippet:
select new map(c.name as name, c.order as order) from Customer c
Instead of returning arrays this query will return a list of maps each containing entries with aliases (the keys) to selected values.
Actually it's possible to let Hibernate return partially loaded entities instead of maps containing the properties of interest. Check out the following example:
select new Customer(c.name, c.order) from Customer c
This query will return lists of customers assuming there is an appropriate constructor.
You should really pay attention with this approach of partially loaded entities because updating these entities could lead to accidently loosing data.


7 comments:
Hi Benjamin,
It gets even more interesting, if we talk about aggregate functions, which do not even return mapped hibernate entities like count(*) or max(*).
Nevertheless, there's also a third method worth being mentioned, namely the org.hibernate.transform.ResultTransformer.
Here we simply return the rows as they are and transform them afterwards into our desired entity. In the following example we use one of Hibernate's out-of-the-box Transformers, which puts each row into a java bean:
@Override
public Object doInHibernate(Session session)
throws HibernateException, SQLException {
Query query = session.createQuery(
" select " +
" g as group," +
" count(g) as count, " +
// we need duration in milli seconds
" sum(t.duration) * 1000 as duration," +
" min(t.startDate) as startDate, " +
" max(t.endDate) as endDate " +
" from Task as t " +
" inner join t.groups as g " +
" where t.compilation = :compilation " +
" group by g.id,g.name,g.compilation " +
" order by g.name "
);
query.setResultTransformer(Transformers.aliasToBean(TaskGroupStats.class));
query.setParameter("compilation", compilation);
return query.list();
}
});
Hi Lars,
thanks for sharing this snippet. ResultTransformer seems to be very interesting for things like that. DISTINCT_ROOT_ENTITY is the only one Ive used so far. :)
Don't instantiate a partial object. Use another object that describes its purpose.
Other than that, good info that seems to be buried in the Hibernate docs.
Hi Lars,
nice post!!!
I was searching for an explanation of "new map(" hibernate query ability and your post came up.
It is a bit confusing though when you describe the part about the new map: "...each containing entries with aliases (the keys) to selected values". You basically explained a map here, but you'r not describing what will be the actual key and what the value in your example:
"select new map(c.name as name, c.order as order) from Customer c"
If I do the following:
List mapsList = session.createQuery("select new map(c.name as name, c.order as order) from Customer c").list();
would this be true:
List> orderMapsList = (List>) mapsList;
Will this way, every map contain one entry with key name and value the order? or will it contain multiple entries?! I am confused!
Kind Regards,
Despot
Thank you Benjamin, you great post helps me solve my problem in 10 minutes.
Hi Benjamin,
I am a newbie to Hibernate.
I have a class Event with id,title and date as properties.
I have mapped it to a table with name EVENTS having the same columns.
I am running following query in java application:
Query evtQ = session.createQuery("select title,date from Event");
and I want the results to be stored in my Event Beans' list.
How do I do it without using Criteria? I mean plain HQL.
Regards,
R J
Benjamin,
Thanks for this post. It helped solving my issue.
Mohan
Post a Comment