I have 4 tables:
job
client
order
client
client
state
state
name
I need to get a client's state name from a job OR order. If job is not null get from job, else get from order.
I tried something like this:
LEFT JOIN job.client jc
LEFT JOIN order.client oc
LEFT JOIN COALESCE(jc.state, oc.state) clientState
but I get an unexpected token: COALESCE exception.
I also tried:
LEFT JOIN job.client jc
LEFT JOIN order.client oc
LEFT JOIN CASE WHEN job IS NOT NULL THEN jc.state ELSE oc.state END clientState
but I get an unexpected token: CASE exception.
Any idea on how to solve this? Should I try multiple JOINS with state table (jc.state and oc.state) and use the CASE in the projection? Isn't there an easier way?
Thanks in advance
Extra info:
This query could be solved like the example below. My main question is if there is a better way of doing this:
SELECT CASE WHEN jcClientState IS NOT NULL THEN jcClientState.code ELSE ocClientState.code END
FROM job job
LEFT JOIN anotherTable anotherTable
LEFT JOIN job.client jc
LEFT JOIN anotherTable.order oc
LEFT JOIN jc.state jcClientState
LEFT JOIN oc.state ocClientState
Assuming HQL supports coalesce (appears as such when doing a quick search), then you can use coalesce like this:
select coalesce(table1.state, table2.state, 'unknown') as state
from table1
left join table 2
on table2.id = table1.id
The coalesce will grab the first non-null value.
Related
We have a HQL SELECT query that, as a result, returns Java objects. To our surprise, some objects are missing in the result list.
I've checked the db for one of the missing objects and could not find a problem. Furthermore, I set a break point in the constructor of 'ParsableObject' that watches for the values of the missing object and it is triggers. But yet, that object is not in the result list.
The result contains some other objects and there is no exception thrown. Are there any known issues that I should look out for?
What I did not do yet: Check the logs of hibernate. I've set hibernate.show_sql to true but did not get a log. But that's a different issue.
The prepared query:
<query name="ObjectDAOHibernate.getSessionObjects">
<query-param name="idSession" type="long"/>
<![CDATA[
select new de.smartshift.ucchecker.model.ParsableObject(
to.idObject, to.objectName, to.description,
tom.codeSize, tom.codeSizeModified,
tom.lineCount, tom.normalizedLineCount, tom.commentLineCount, tom.lineCountModified,
tot.objectTypeCode,
ocst.idObjectState,
odst.idObjectState,
opst.idObjectState,
otst.idObjectState,
oust.idObjectState,
sapr3data.devClass,
to.standard,
to.tblFolder.relevant)
from
de.smartshift.ucchecker.db.hib.TblObject to join to.tblFolder tf
join tf.tblSession ts
join to.tblObjectType tot
join to.tblObjectMetadata tom
join to.tblObjectProcessingState tops
join tops.tblObjectStateByRefidCustomerState ocst
join tops.tblObjectStateByRefidDownloadState odst
join tops.tblObjectStateByRefidParserState opst
join tops.tblObjectStateByRefidToolState otst
join tops.tblObjectStateByRefidUploadState oust
join to.tblSapr3Data sapr3data
where
ts.idSession=:idSession
order by
to.objectName ASC, tot.objectTypeCode ASC
]]>
I need to sort topics by latest post. Could someone please help me with this hibernate query:
unexpected AST node: query
[SELECT t
FROM Topic t
ORDER BY
(SELECT MAX(p.createdOn) FROM Post p WHERE p.topic.id = t.id)
DESC]
What is the issue here?
SELECT topic FROM Post ORDER BY createdOn
I think that this JPQL query should work
select t.id, t.description, max(p.createdOn) as maxCreationTime
from Topic t inner join t.posts p
group by t.id, t.description
order by maxCreationTime
If you want to include topics that have not related posts.
select t.id, t.description, max(p.createdOn) as maxCreationTime
from Topic t left join t.posts p
group by t.id, t.description
order by maxCreationTime
You have to specify the selected fields from Topic in order to make the aggregation function max work. Hope this helps.
I'm joining one table to another. The join works. I want to restrict the results to records with an "Error" message that can be in either table. When I do the following, I get no results back, yet I know there should be 2.
Criteria criteria = session.createCriteria(TableName.class);
criteria.createAlias("someList", "things");
Criterion restriction1 = Restrictions.eq("status", "Error");
Criterion restriction2 = Restrictions.eq("things.anotherStatus", "Error");
criteria.add(Restrictions.or(restriction1, restriction2));
finalList = criteria.list();
I noticed that the restrictions by themselves actually work. So, if I only do the first restriction on the original table with no alias OR if I only do the second restriction on the alias table, then I get 1 result each time.
Also, a simple join SQL query like the one below works as expected:
Select count(*)
From table1 t1
Left join table2 t2 on t1.id = t2.another_id
Where t1.status = 'ERROR' or t2.anotherStatus = 'ERROR'
How can I get this right in Hibernate?
EDIT 1: I now see that Hibernate does an Inner Join when I use the #JoinColumn annotation. How can I change it to do an Outer Join instead?
EDIT 2: Even adding #Fetch(FetchMode.JOIN) still results in an inner join! What gives? The documentation clearly says it will do an outer join. The annotation now looks like this:
#OneToMany
#JoinColumn(name="ID_FK")
#Fetch(FetchMode.JOIN)
private List<Thing> things;
Answer: use criteria.createAlias("someList", "things", JoinType.LEFT_OUTER_JOIN); instead.
Explanation: When no JoinType is specified, createAlias does an inner join by default.
How to add groupBy criteria to the code below? Because if I add criteriaQuery.groupBy(from.get(minutis.Preke_.prId)); - I get exactly the same SQL statement (without groupBy):
CriteriaBuilder cb = MinutisManager.getInstance().getCriteriaBuilder();
CriteriaQuery criteriaQuery = cb.createQuery(minutis.Preke.class);
Root<minutis.Preke> from = criteriaQuery.from(minutis.Preke.class);
from.fetch(minutis.Preke_.tiekejai, JoinType.LEFT).fetch(minutis.PrekeTiekejas_.tiekejas, JoinType.LEFT);
//criteriaQuery.groupBy(from.get(minutis.Preke_.prId));
TypedQuery<minutis.Preke> typedQuery = MinutisManager.getInstance().createQuery(criteriaQuery);
typedQuery.setFirstResult(0);
typedQuery.setMaxResults(100);
typedQuery.getResultList();
EDIT 1:
criteriaQuery.distinct(true) is not an option for me. Because that command hangs the whole statement and if I use EXPLAIN:
If I use GROUP BY on the query, then EXPLAIN is:
EDIT 2:
I get this SQL statement with and without criteriaQuery.groupBy(from.get(minutis.Preke_.prId));
SELECT ... FROM preke t1 LEFT OUTER JOIN preke_tiekejas t0 ON (t0.pr_id = t1.pr_id) LEFT OUTER JOIN tiekejas t2 ON (t2.tiek_id = t0.tiek_id) LEFT OUTER JOIN gamintojas t3 ON (t3.gam_id = t1.gam_id) LEFT OUTER JOIN google_compare t4 ON (t4.pr_id = t1.pr_id) LEFT OUTER JOIN grupe t5 ON (t5.pgs_id = t1.pgs_id) LEFT OUTER JOIN preke_kaina t6 ON (t6.pr_id = t1.pr_id) ORDER BY t1.pr_id LIMIT ?, ?
The SQL for the GROUP BY query should definitely contain a GROUP BY. Ensure that you are compiling and deploying the code correctly.
It could be a bug that the group by is ignored, as normal group by queries will not select object, but aggregated values. Check that you are using the latest release, and perhaps log a bug, or try JPQL.
In general your query does not make any sense, normally on a group by query you can only select the fields that you grouped by, or aggregation functions.
Perhaps consider batch fetching instead of join fetching.
http://java-persistence-performance.blogspot.com/2010/08/batch-fetching-optimizing-object-graph.html
I will file a bug in Eclipselink, because if I change fetch line with QueryHints, everything works:
Change this (with this line I get duplicate Preke entities with populated children entities):
from.fetch(minutis.Preke_.tiekejai, JoinType.LEFT).fetch(minutis.PrekeTiekejas_.tiekejas, JoinType.LEFT);
To this (with this lines I get unique Preke entities with populated children entities):
typedQuery.setHint(QueryHints.LEFT_FETCH, "Preke.tiekejai");
typedQuery.setHint(QueryHints.LEFT_FETCH, "Preke.tiekejai.tiekejas");
I get my desired result.
EDIT 1:
The bug really exists, now max resulsts is not working. Both cases typedQuery is identical.
typedQuery.setMaxResults(100);
System.out.println(typedQuery.getResultList().size()); //prints 73
typedQuery.setMaxResults(500);
System.out.println(typedQuery.getResultList().size()); //prints 413
No problem, I found the bug report, here it is, just in case someone else needs it.Criteria api ignores group by statement
I have a following entity structure.
Venue -- n:1 -- Schedule -- 1:n -- Event
I have a query to get counts of all schedule in Venues:
SELECT v, count(s.event) FROM Venue v
LEFT JOIN i.schedule s
GROUP BY i.id ORDER BY count(s.event) asc;
The problem is that this query will never output venues, that have zero events. The problem is with Hibernate, which generates following:
select ..., count(schedule4_.event_id) as col_7_0_
from Venue venue0_
left outer join event_schedule schedule4_ on venue0_.id=schedule4_.venue_id,
Event event5_
where schedule4_.event_id=event5_.id and ...
You can see, that Hibernate tries to join Event on Schedule even though I did not request that. Obviously if the Schedule does not exist, joining Event does not make any sense.
(I simpified the query, if there is some typo, it should not have any impact on the problem).
Try with the following query:
select v.id, count(e.id) from Venue v
left join v.schedule s
left join s.events e
group by v.id order by count(e.id) asc;