Sub-queries in associations with hibernate - java

Anyone knows if is possible to use sub-queries in associations like this query bellow?
SELECT l, o
FROM User u
INNER JOIN u.licenses l
LEFT JOIN l.orders o
WITH o.id = (
SELECT MAX(lastOrder.id)
FROM Order lastOrder
WHERE lastOrder.license = l
)
WHERE u.idtPerson = :idtPerson
AND l.statusCode != 3
I found this workaround...
SELECT l, o
FROM User u
INNER JOIN u.licenses l
LEFT JOIN l.orders o
WHERE u.idtPerson = :idtPerson
AND l.statusCode != 3
AND (
o.id IS NULL
OR o.id = (
SELECT MAX(lastOrder.id)
FROM Order lastOrder
WHERE lastOrder.license = l
)
)
But I really believe that is not a good solution, any suggestions?

Another option will be making the subquery in another query, list it with maxresults=1, and pass it by parameter to the original query.
Something like this:
Query hqlQuery = session.createQuery("SELECT MAX(lastOrder.id)
FROM Order lastOrder
WHERE lastOrder.license = l");
hqlQuery.setMaxResults(1);
List results = hqlQuery.list();
Integer maxId = null;
if (!results.isEmpty()){
maxId = results.get(0);
}
Query hqlQuery1 = session.createQuery("SELECT l, o
FROM User u
INNER JOIN u.licenses l
LEFT JOIN l.orders o
WITH o.id = :maxId
WHERE u.idtPerson = :idtPerson
AND l.statusCode != 3");
hqlQuery1.setParameter("maxId", maxId);
hqlQuery1.list();
...etc...
Maybe this will work for you

Related

how to write inner join a selected table query in hibernate.ejb

I have a query working fine:
StringBuilder query = new StringBuilder(
"select o.deviceName, o.deviceOs, o.loginOn, e.username, e.name, e.idNo from LoginHistory o, User e ");
query.append(" where o.userId = e.userId");
Query q = getEm().createQuery(query.toString());
This createQuery() will go to createQuery() in class org.hibernate.ejb.AbstractEntityManagerImpl.
I want to edit the query to get the last login for each user. The following SQL query can run in a db2 command successfully:
select m1.*, m2.*
from tibs.LoginHistory m1 inner join (
select userId, max(loginOn) as loginOn from tibs.LoginHistory group by userId
) m2
on m1.userId = m2.userId and m1.loginOn = m2.loginOn;
But when I try to apply this in my code above, it will hit QuerySyntaxException: unexpected token: at ( after inner join.
Code is something like:
StringBuilder query = new StringBuilder(
"select o.deviceName, o.deviceOs, o.loginOn, e.username, e.name, e.cif, e.idNo from LoginHistory o, ECUser e ");
query.append("inner join (select o2.userId, o2.max(loginOn) as loginOn from LoginHistory group by userId) o2 ");
query.append("on o.userId = o2.userId and o.loginOn = o2.loginOn");
query.append(" where o.userId = e.userId");
Is this workable in this way? If yes, what syntax should I use?
Or does Hibernate not accept this, and I need to do it in another way?
Add on**
Even I change my query to this, still the same:
StringBuilder query = new StringBuilder(
"select o.deviceName, o.deviceOs, o.loginOn, e.username, e.name, e.cif, e.idNo from LoginHistory o, ECUser e ");
query.append("inner join (select o2.userId, o2.max(loginOn) as loginOn from LoginHistory o2 group by userId) ");
query.append("on o.userId = o2.userId and o.loginOn = o2.loginOn");
query.append(" where o.userId = e.userId");
I think the inner query should be as follows (note position of o2):
(select o2.userId, o2.max(loginOn) as loginOn from LoginHistory o2 group by userId)
Please name variables appropriately to facilitate comprehension.
It would be helpful if o2 was renamed to lh, since it represents LoginHistory entity.
(select lh.userId, lh.max(loginOn) as loginOn from LoginHistory lh group by userId)
You can use the following query:
select o.deviceName, o.deviceOs, o.loginOn, e.username, e.name, e.idNo
from LoginHistory o, User e
where o.id = (select max(lh.id) from LoginHistory lh where lh.userId = e.userId)

Oracle Stored Procedure Slow Performance

i have a simple stored procedure. i use this to show data from my db. i want to optimize this query because i think this is slow. 31 seconds for 220.000 rows. so this is my query
BEGIN
sql_base :=
'SELECT
p.id
,p.cis
,p.account_no
,p.name
,p.address
,p.village_name
,p.postal_code
,p.subdistrict_name
,p.regency_name
,p.province_name
,p.country_name
,m.group_id
,i.name
,m.id
,m.name
,m.address
,m.village_name
,m.postal_code
,m.subdistrict_name
,m.regency_name
,m.province_name
,m.country_name
,listagg (mMcc.name, '','') within group (order by mMcc.name) merchantMccName
,o.mid
,o.name
,o.mcc_id outletMccId
,REPLACE(REPLACE(o.jenis_outlet,''ecomm'',''e-commerce''),''retail'',''toko'') jenisOutlet
,o.MODIFIEDDATE
,o.CREATEDDATE
,o.CC_testing_ACCOUNTNO outletCcAccountNo
,o.DEBIT_testing_ACCNO outletDebitAccountNo
,MCC.name outletMccName
,o.MCC_CODE outletMccCode
,m.code merchantCode
,p.jenisn abah jenisn abah
,p.segmenn abah segmenn abah
,p.IDENTITY_NO identityNo
,p.IDENTITY_TYPE identityType
,o.status status
,NVL(o.ISOUTLET, 0) isOutlet
,NVL(p.IS_ACCOUNT_testing, 0) isAccounttesting
,p.ACCOUNT_OTHERBANK_NO accountOtherbankNo
,p.ACCOUNT_OTHERBANK_BANKNAME accountOtherbankBankname
,p.ACCOUNT_OTHERBANK_NO pemilikOtherBankAccountNo
,o.ADDRESS1 outletAddress1
,o.ADDRESS2 outletAddress2
,o.VILLAGE_NAME outletVillageName
,o.POSTAL_CODE outletPostalCode
,o.SUBDISTRICT_NAME outletSubdistrictName
,o.REGENCY_NAME outletRegencyName
,o.PROVINCE_NAME outletProvinceName
,C E WHEN NVL(o.IS_CC_TESTING,0)=1 THEN ''TESTING'' ELSE TO_CHAR(o.CC_OTHERBANK_NAME) END outletCcBankName
,C E WHEN NVL(o.IS_DEBIT_TESTING,0)=1 THEN ''TESTING'' ELSE TO_CHAR(o.CC_OTHERBANK_NAME) END outletDebitBankName
,NVL(o.IS_CC_OTHERBANK,0) isCcOtherBank
,NVL(o.IS_CC_TESTING,0) is_cc_testing
,NVL(o.IS_DEBIT_testing,0) is_debit_testing
,o.CC_OTHERBANK_ACCNO ccOtherBankAccNo
,o.QRIS_STATIS_NMID nmid
,o.AGENT_BANK_CODE outletAgentBank
FROM PEMILIK p
LEFT JOIN mytable m ON p.ID = m.PEM_ID
LEFT JOIN mytable2 i ON m.GROUP_ID = i.ID
INNER JOIN mytable3 o ON m.ID = o.MERCH_ID
LEFT JOIN mytable4 mMcc ON m.ID = mMcc.MERCH_ID
LEFT JOIN mytable5 mcc ON MCC.ID = o.MCC_ID
GROUP BY
*SAME LIKE SELECT*;
final_result:='SELECT rec.*, count (*) over ()CountData FROM ('
|| sql_base || ') rec '
||WHERE_Q
||ORDERBY_Q||' '||PAGING_Q ;
OPEN O_RESULT_REC FOR
final_result;
i already tried to change the query but still i think my query still not good. any tips to improve my query? should i change the connection in java? or this is just query problem?

derby error "Subquery is only allowed to return a single column."

I got this exception when calling the method that calls this query:
SELECT s FROM Survey s
WHERE s.idsurvey NOT IN
(SELECT DISTINCT s FROM Useranswer ua
JOIN ua.iduser u
JOIN ua.idanswer a
JOIN a.idquestion q
JOIN q.idsurvey s
WHERE
ua.iduser.iduser = u.iduser
AND ua.idanswer.idanswer = a.idanswer
AND a.idquestion.idquestion = q.idquestion
AND q.idsurvey.idsurvey = s.idsurvey
AND u.iduser = :iduser
)
order by s.dateEnd
Any help?
The query seems fine.
I was trying to solve this problem for almost 2 hours.
I've found a solution using native sql.
String query = "select s.IDSURVEY, s.DATE_END from survey s where s.IDSURVEY not IN (select distinct s.IDSURVEY from survey s join question q on s.IDSURVEY = q.IDSURVEY join answer a on q.IDQUESTION = a.IDQUESTION join useranswer ua on a.IDANSWER = ua.IDANSWER where ua.IDUSER = "+iduser+") order by s.DATE_END";
return (List<Survey>)em.createNativeQuery(query).getResultList();

Hibernate HQL issue expecting IDENT found "*"

I need get all data from relative table so I'm using something like this (i would use it in sql)
private static final String SELECT_OOPR_TO_SEND = "SELECT R.* " +
"FROM offerOrderProjectRel R, offerOrder O, project P " +
"WHERE P.id = R.project_id and O.id = R.offer_order_id " +
"and O.type = 'ORDER' and (P.status = 'PENDING' or P.status ='PROTECTED')" ;
;
#SuppressWarnings("unchecked")
public List<OfferOrderProjectRel> findAllOfferOrderToSendToSalesmans() {
Query q = getSession().createQuery(SELECT_OOPR_TO_SEND);
List<OfferOrderProjectRel> list = q.list();
return list;
}
After lauching this code i'm getting that error :
org.hibernate.hql.internal.ast.QuerySyntaxException: expecting IDENT,
found '**' near line 1, column 10 [SELECT R.* FROM offerOrderProjectRel
R, offerOrder O, project P WHERE P.id = R.project_id and O.id =
R.offer_order_id and O.type = 'ORDER' and (P.status = 'PENDING' or
P.status ='PROTECTED')]
So how can I obtain all data from column R with hibernate?
The method createQuery expects an HQL query string.
HQL is an object-oriented querying language.
HQL interprets SELECT R.* as select the member field * of the object R.
But * is not a member field of R. Is it?..
To select all the member fields of R use:
SELECT R
FROM offerOrderProjectRel R, offerOrder O, project P
WHERE P.id = R.project_id and O.id = R.offer_order_id
and O.type = 'ORDER' and (P.status = 'PENDING' or P.status ='PROTECTED')
you use SQL query, not hql query, so it should be
Query q = getSession().createSQLQuery(SELECT_OOPR_TO_SEND);
For people that received the "expecting IDENT found “*”" error when using org.springframework.data.jpa.repository.Query and found this question I'll add that you can change the nativeQuery flag to true:
#Query(value = "SELECT * FROM table1", nativeQuery = true)
List<Object> myFindAll();

Syntax Error for HQL JOIN Statment

I'm trying to create a HQL query to join a result of a select with another table. What I have currently is
SELECT e FROM Experience e JOIN (SELECT f FROM Follow f WHERE f.username = :username AND f.contentType = :contentType) AS A ON (e.experienceId = A.contentId);
Its SQL equivalent that currently works is
SELECT t_experiences.* FROM t_experiences JOIN (SELECT * FROM t_follows WHERE t_follows.username = :username AND t_follows.content_type = :contentType) AS A ON (t_experiences.experience_id = A.content_id);
Where t_experiences.experience_id is equivalent to Experience.experienceId, etc. The current error in the HQL is on the first ( with unexpected token: ( error.
Any help would be greatly appreciated!
Why don.t you try this:
SELECT e.experienceId FROM Experience e, Follow f WHERE f.username = :username AND f.contentType = :contentType AND (e.experienceId = f.contentId);
I think this should work for you.
Note: Replace e.experienceId by parameters which you want.

Categories