HQL limit in subselect query - java

I want to insert foreign key of one table in another on basis of certain criteria. Structure is like
insert into CustomerResult(customer,draw) select c.idCustomer, from Customer c,Draw d where ..... and c.idCustomer in (select cc.idCustomer from Customer cc where ..... limit 10)
here i want to insert only fix no of records which fulfill certain criteria. I know hql has no limit keyword but want to implement like this. any suggestion?

I don't think that what you want to do (use limit in subquery) is directly supported by Hibernate. Have a look at these previous answers:
How to set a limit to inner query in Hibernate?
How do you do a limit query in HQL?

Related

What is the limit of hibernate in clause

we know hibernate has this in clause:
Criteria criteria = session.createCriteria(User.class);
criteria.add(Restrictions.in(userIds));
Is there any limit on the size of userIds (which is an ArrayList, say)?
Thanks
It actually depends on the particular database you use. For example in Oracle this limit is 1000.
If you need to pass more values you need to use another approach. For example put the values into a temporary table and then do a select where id in (select id from temptable) query.

Is it possible to merge these two queries?

I'm writing a sql query to count objects. I have about 50 pre-written queries, and each of them is essentially written like so:
"select count(1) from SOME_TABLE where identifier = :ID"
I have it in Java. SOME_TABLE is already written into the query (different for each query). At runtime, a switch/case determines which query to execute and which ID to send it.
Essentially, there are various queries which can be called, but ID is the only thing that changes inside the queries.
So, if I want to count all the pinetrees in a forest, I'd send pineTree as an ID to a query that counts Tree. Simple enough. As I mentioned, there's a giant switch/case which determines TABLE_NAME, ID, and the exact query.
The problem is, I'm trying to count all of the objects of a table, and I'm trying to count them with various IDs. For example:
query1: "select count(1) from LIST_OF_TOYS where animalId = theListOfIDsfromQuery2"
query2: "select allThePetIDs from LIST_OF_PETS where ownerId = :myID
This is essentially what I'm trying to do. I want to count all the toys owned by my pets, but there is no direct link between my ID and the LIST_OF_TOYS table.
I know how to do this with two separate queries, but I would strongly prefer to write one query that just takes ownerId as a parameter, so that I can add it to my giant switch/case (and keep my code neat). I can write the query however I want, but I was wondering if it's possible to do this as a single query and a single argument. Thanks for the help!
select count(1) from LIST_OF_TOYS where animalId in (select allThePetIDs from LIST_OF_PETS where ownerId = :myID)

How to limit entity list-property size with JPQL?

I have this query in JPQL
FROM User u INNER JOIN FETCH u.addresses a WHERE u.id =:id ORDER BY a.id DESC
Sometimes a user may have more than ten addresses and I want to limit this to ten. If the user wants to he may load more ten adresses later.
I tried using setMaxResults(int) but I wasn't sucessfull because since I get only one user I think jpql understands it as it is right even if the query translated and used in my database brings me more than one result.
Is it possible to to what I want? If so, how?
EDIT:
I have the SQL that brings me what I want, but I want this in jpql if possible.
SELECT
*
FROM
user u INNER JOIN address a ON u.id_user = a.id_user
WHERE
u.id_user = '123' AND ROWNUM = 1
ORDER BY
a.id_address desc;

How to order by count() in JPA

I am using This JPA-Query:
SELECT DISTINCT e.label FROM Entity e
GROUP BY e.label
ORDER BY COUNT(e.label) DESC
I get no errors and the results are sorted almost correct but there are some values wrong (either two values are flipped or some single values are completly misplaced)
EDIT:
Adding COUNT(e.label) to my SELECT clause resolves this problem for this query.
But in a similar query which also contains a WHERE clause the problem persists:
SELECT DISTINCT e.label, COUNT(e.label) FROM Entity e
WHERE TYPE(e.cat) = :category
GROUP BY e.label
ORDER BY COUNT(e.label) DESC
You might need to include the COUNT(e.label) in your SELECT clause:
SELECT DISTINCT e.label, COUNT(e.label)
FROM Entity e
GROUP BY e.label
ORDER BY COUNT(e.label) DESC
UPDATE: Regarding the second query please read section 8.6. Polymorphic queries of the EntityManager documentation. It seems that if you make your queries in a way that requires multiple SELECTs, then the ORDER BY won't work anymore. Using the TYPE keyword seems to be such a case. A quote from the above link:
The following query would return all persistent objects:
from java.lang.Object o // HQL only
The interface Named might be implemented by various persistent classes:
from Named n, Named m where n.name = m.name // HQL only
Note that these last two queries will require more than one SQL SELECT. This means that the order by clause does not correctly order the whole result set. (It also means you can't call these queries using Query.scroll().)
For whatever reason the following style named query didn't work for me:
SELECT DISTINCT e.label, COUNT(e.label)
FROM Entity e
GROUP BY e.label
ORDER BY COUNT(e.label) DESC
It could be because I am using an old version of Hibernate. I got the order by working by using a number to choose the column to sort by like this:
SELECT DISTINCT e.label, COUNT(e.label)
FROM Entity e
GROUP BY e.label
ORDER BY 2 DESC
Can't see how the order could be incorrect. What is the incorrect result?
What is the SQL that is generated, if you try the same SQL directly on the database, does it give the same incorrect order?
What database are you using?
You could always sort in Java instead using sort().

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!
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.
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.
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.
You can not fetch random rows efficiently, sorry. Hibernate can only do what SQL does, and random row fetch simply is not part of any standard SQL implementation I know - actually it is to my knowledge not part of ANY SQL that I am aware of (anyone please enlight me).
And as Hibernate is an O/R mapper, and not a wonder machine, it can only do what the underlying database supports.
If you have a known filed with ascending numbers and know start and end, you can generate a random number on the computer and ask for that row.
The answer by #PSV Bhat is difficult if you are dynamically generating your Criteria. Here is a solution that extends hibernate Order class:
import org.hibernate.Criteria;
import org.hibernate.criterion.Order;
private void addOrderByToCriteria(Criteria criteria) {
criteria.addOrder(Order.asc("foobar"));
criteria.addOrder(ORDER_RANDOM);
}
private static final OrderRandom ORDER_RANDOM = new OrderRandom();
private static class OrderRandom extends Order {
public OrderRandom() {
super("", false);
}
#Override
public String toSqlString(Criteria criteria, CriteriaQuery criteriaQuery) {
return "RANDOM()"; // or RAND() or whatever this is in your dialect
}
}

Categories