Get count from query - jpa

I am using mysql 5.5 with openjpa 2.3.0.
I have entities with namedQueries (generated in netbeans - I would like to be able to use this), for example:
#NamedQuery(name = "User.findAll", query = "SELECT u FROM User u")
#NamedQuery(name = "User.findByGender", query = "SELECT u FROM User u WHERE u.gender = :gender")
I am creating restfull aplication with paged results. I would like to return for every paged result the Content-Range header as 1-20/250 where 20 is pagesize, 250 total count.
I tried to create a query
entityManager.createNativeQuery("SELECT count(1) FROM (" + namedQuery.toString() + ") as foo;");
where I could dynamicaly insert any named query and return the count without returning the result list -> it should be faster.
When I execute this, exception occurs
SQL state 42S22: Unknown column 'u' in 'field list'
Executing the query itself in entitymanager is ok.
Can I use the entity manager or criteria builder to create a query for counting results without returning the result list (and without writing for every namedQuery a count duplicate)? thank you for helping.

You are mixing JPQL with native queries. JPQL says SELECT u FROM entity u, SQL would be SELECT * FROM entity u or SELECT col1,col2,col3 FROM entity u
You could write a JPQL named query counting the stuff, e.g. SELECT COUNT(u) FROM entity u. A getSingleResult() would then return an Object[], whose first element contains the count.
Not nice but working. Why do You have to query for the number anyway? Pagination means next = lastindex+pagesize. if next < lastindex+pagesize, the end is reached.

Related

Count in Spring Data JPQL join query throwing IllegalArgumentException

I have a query using JPQL in the annotation #Query in Spring Data which looks like below
#Query(value = "select distinct a from EntityA as a left join fetch a.listEntityB as b where ...")
public List<EntityA > find....(#Param("") String value, Pageable pageable);
Now I need to know the total number of records of the query. As Pageable is giving me partial list, I am writing another count query without the Pageable. My count query looks like below:
#Query(value = "select count(distinct a) from EntityA as a left join fetch a.listEntityB as b where ...)
public long count...(#Param("") String value);
However, I am getting "IllegalArgumentException: Validation failed for query" error from this query to count the records. When I change the count query to "select count(distinct a) from EntityA" , it works fine. I am not sure what is the problem when I use the join. I did not get any helpful documents so far. Is there any better solution to get the total number of records for the Pageable query.
Put the CountQuery in the same annotation as the query itself. So
#Query(value = "select ...", countQuery = "select count..")
public List<EntityA > find....(#Param("") String value, Pageable pageable);
Also remove the "fetch" from the countQuery.
To get the total records, you can just reference the page.getTotalElements() to return the total number of records.

How to write this query in JPA

How to write this query in JPA?
select sol.ID_UNICA, sol.version
from uexdfr01.SOLUTION sol
join
(select solution4_.ID_UNICA, max(solution4_.version) as maxVersion
from uexdfr01.ORDER order3_
inner join uexdfr01.SOLUTION solution4_ on order3_.ID_SOLUTION=solution4_.ID_SOLUTION
where solution4_.ID_UNICA in (130,139,143,129,126,128,141,121,124,131)group by solution4_.ID_UNICA) as groupedtt
on sol.ID_UNICA = groupedtt.ID_UNICA
AND sol.version = groupedtt.maxVersion*
If you are not sure about db relationships use createNativeQuery and pass your query inside parenthesis.
Query selectRecords = getEntityManager().createNativeQuery(sqlQuery.toString());
Returned values are type of Objects so make sure to assign them in List as following way..
List<Object[]> data= selectRecords.getResultList();

Get results from HQL query with the same order as given list

I'm trying make a query with HQL that will stay with the same order as given list of IDs. I know it's possible with SQL but I can't find any way to do it with HQL (and I cannot do it with native SQL because I got many joins)
Example
fingerIds = [3,1,10,4]
SELECT p FROM People p
JOIN FETCH p.fingers f
WHERE f.id IN :fingerIds
DB: PostgreSQL 10.4
Hibernate: 4.3.11.Final
Eg. Given list of IDs: [3,1,10,4]
Actual result's order: [1,3,4,10]
Expected result's order: [3,1,10,4]
You can obtain the order by adding to your query the keyword FIELD, in your example:
SELECT p FROM People p
JOIN FETCH p.fingers f
WHERE f.id IN :fingerIds
ORDER BY FIELD(f.ID,3,1,10,4)
Ofc you can replace the numbers with your variable :fingerIds
You can find more about that command here.
Returns the index (position) of str in the str1, str2, str3, ... list. Returns 0 if str is not found.

Get native SQL from QueryDSL JPA (JPAQuery or JPQLQuery)

I have a requirement to count the number of group by records for pagination purpose. For example:
select count(*) from (
select name, count(id) from customer
group by name
);
However it couldn't be achieved via QueryDSL due to the limitation of JPA
where JPQL doesn't allows to select count from sub query.
Is it possible to get the native SQL from QueryDSL JPAQuery or JPQLQuery? My plan is to construct and execute the select count native SQL statement via EntityManager.
String subQueryNativeSQL = "..."; // native SQL from QueryDSL
Query q = em.createNativeQuery("select count(*) from (" + subQueryNativeSQL + ")");
long count = (long) q.getSingleResult();
Both JPAQuery and JPQLQuery implement Projectable interface and implement count() method - and you ain't need subqueries

Fairly complex LINQ to Entities query

I have two entities, assume they are called Container and Record. They have a master-child relationship: a 'container' can hold many records.
The Records table in the database has the following columns:
Id
Date
Container_Id
RecordType_Id
The Record entity does not have any navigation properties that back reference the Container.
I am writing a LINQ query for my repository that will retrieve ONLY the records for a container that have the most recent date for each RecordType_Id. All older records should be ignored.
So if a container has say 5 records, one for each RecordType_Id, with the date 24/May/2011. But also has another 5 records for each RecordType_Id but with the date 20/May/2011. Then only the first 5 with the 24/May date will be retrieved and added to the collection in the container.
I came up with an SQL query that does what I need (but maybe there is some more efficient way?):
select t.*
from Records t
inner join (
select Container_Id, RecordType_Id, max(Date) AS MaxDate
from Records
group by Container_Id, RecordType_Id ) g
on t.Date = g.MaxDate
and t.Container_Id = g.Container_Id
and t.RecordType_Id = g.RecordType_Id
order by t.Container_Id
, t.RecordType_Id
, t.Date
However I am struggling to translate this into a proper LINQ query. EF is already generating a fairly large query all by itself just to load the entities, which makes me unsure of how much of this SQL query is actually relevant to the LINQ query.
Off the top of my head:
var q = from c in Container
from r in c.Records
group r by r.RecordType.RecordType_Id into g
select new
{
Container = c,
RecordType_Id = g.Key,
Records = from gr in g
let maxDate = g.Max(d => d.Date)
where gr.Date == maxDate
select gr
};
Try using LinqPad, it helps you test linq queries easily. Even against an existing EF model (which is in your project). Visit http://www.linqpad.net/