Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

HQL query for entity with max value

I have a Hibernate entity that looks like this (accessors ommitted for brevity):

@Entity @Table(name="FeatureList_Version") @SecondaryTable(name="FeatureList",     pkJoinColumns=@PrimaryKeyJoinColumn(name="FeatureList_Key")) public class FeatureList implements Serializable {      @Id     @Column(name="FeatureList_Version_Key")     private String key;      @Column(name="Name",table="FeatureList")     private String name;      @Column(name="VERSION")     private Integer version;  } 

I want to craft an HQL query that retrieves the most up to date version of a FeatureList. The following query sort of works:

Select f.name, max(f.version) from FeatureList f group by f.name 

The trouble is that won't populate the key field, which I need to contain the key of the record with the highest version number for the given FeatureList. If I add f.key in the select it won't work because it's not in the group by or an aggregate and if I put it in the group by the whole thing stops working and it just gives me every version as a separate entity.

So, can anybody help?

like image 706
rjsang Avatar asked Dec 21 '10 08:12

rjsang


People also ask

How do I give a limit in HQL?

1 Answer. Try: // SQL: SELECT * FROM table LIMIT start, maxRows; Query q = session.

Can we use select * in HQL?

Keywords like SELECT, FROM, and WHERE, etc., are not case sensitive, but properties like table and column names are case sensitive in HQL.

Is HQL and JPQL same?

The Hibernate Query Language (HQL) and Java Persistence Query Language (JPQL) are both object model focused query languages similar in nature to SQL. JPQL is a heavily-inspired-by subset of HQL. A JPQL query is always a valid HQL query, the reverse is not true however.


2 Answers

The straightforward version of this query looks like this (assuming that (name, version) pairs are unique):

select f from FeatureList f  where f.version =       (select max(ff.version) from FeatureList ff where ff.name = f.name) 
like image 119
axtavt Avatar answered Sep 22 '22 16:09

axtavt


I made a scenario here,


Table

key          name                 version          ----------- -------------------- -----------  1           adeel                1            2           adeel                2            3           adeel                3            4           ahmad                1            5           ahmad                2            6           ahmad                3            7           ahmad                4            8           ansari               1            9           ansari               2            10          ansari               3            

Result using your original query

>> select f.name, max(f.version) from FeatureList f group by f.name  name                 max(f.version)  -------------------- ------------  adeel                3             ahmad                4             ansari               3             

Result using your desired query

>> select fl.* from FeatureList fl     where (fl.name, fl.version) in (select f.name, max(f.version)                                             from FeatureList f group by f.name);  key          name                 max(fl.version)   ----------- -------------------- -----------  3           adeel                3            7           ahmad                4            10          ansari               3            

NB: Tried it using MySQL this time. Its working. I am pretty sure MS SQL Server also have IN (...) operator. You just need to use session.createNativeQuery() in Hibernate.


Edited to work on axtavt's answer

As we found out this can be made as simple as,

select f from FeatureList f  where f.version =       (select max(ff.version) from FeatureList ff where ff.name = f.name) 

Now try the same using Hibernate Criteria API,

DetachedCriteria versions = DetachedCriteria.forClass(FeatureList.class, "f")     .setProjection( Property.forName("f.version").max())     .add(Property.forName("f.name").eqProperty("fl.name"));  session.createCriteria(FeatureList.class, "fl")     .add( Property.forName("fl.version").eq(versions) )     .list(); 
like image 27
Adeel Ansari Avatar answered Sep 18 '22 16:09

Adeel Ansari