Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Hibernate Criteria API: get n random rows

I can't figure out how to fetch n random rows from a criteria instance:

Criteria criteria = session.createCriteria(Table.class);
criteria.add(Restrictions.eq('fieldVariable', anyValue));
...

Then what? I can't find any doc with Criteria API

Does it mean I should use HQL instead?

Thanx!

EDIT: I get the number of rows by:

int max = criteria.setProjecxtion(Projections.rowCount()).uniqueResult();

How do I fetch n random rows with indexes between 0 and max? Thx again!

like image 591
Hadrien Avatar asked May 11 '10 12:05

Hadrien


3 Answers

Actually it is possible with Criteria and a little bit of tweaking. Here is how:

Criteria criteria = session.createCriteria(Table.class);
criteria.add(Restrictions.eq("fieldVariable", anyValue));
criteria.add(Restrictions.sqlRestriction("1=1 order by rand()"));
criteria.setMaxResults(5);
return criteria.list();

any Restrictions.sqlRestriction will add keyword 'and'; so to nullify its effect, we shall add a dummy condition and inject our rand() function.

like image 105
PSV Bhat Avatar answered Nov 07 '22 12:11

PSV Bhat


First of all, be aware that there is no standard way to do this in SQL, each database engine uses its own proprietary syntax1. With MySQL, the SQL statement to get 5 random rows would be:

SELECT column FROM table
ORDER BY RAND()
LIMIT 5

And you could write this query in HQL because the order by clause in HQL is passed through to the database so you can use any function.

String query = "SELECT e.attribute FROM MyEntity e ORDER BY RAND()";
Query q = em.createQuery(query);
q.setMaxResults(5);

However, unlike HQL, the Criteria API currently doesn't support ORDER BY Native SQL (see HHH-2381) and in the current state, you would have to subclass the Order class to implement this feature. This is doable, refer to the Jira issue, but not available out of the box.

So, if really you need this query, my recommendation would be to use HQL. Just keep in mind it won't be portable.

1 Other readers might want to check the post SQL to Select a random row from a database table to see how to implement this with MySQL, PostgreSQL, Microsoft SQL Server, IBM DB2 and Oracle.

like image 35
Pascal Thivent Avatar answered Nov 07 '22 11:11

Pascal Thivent


The Criteria API doesn't offer facilities for this. In MySQL however, you can use ORDER BY RAND() LIMIT n for this where n represents the number of random rows you'd like to fetch.

SELECT col1, col2, col3 FROM tbl ORDER BY RAND() LIMIT :n

You indeed need to execute it as HQL.

like image 43
BalusC Avatar answered Nov 07 '22 11:11

BalusC