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

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)

Related

Using a Query, Joining 4 tables in Hibernate Mapping

Currently i'm using PostgreSQL database in my Spring MVC web application. I'm able to get the values when i execute the query in PgAdmin tool.
In my query, I'm trying to join 4 tables and get the values.
My query is:
SELECT (s.school_id, u.first_name, u.last_name, u.username, u.email, p.plan_name, s.start_date, s.end_date, s.subscription_price, (SELECT COUNT(*) FROM school_user t WHERE t.user_type = 'T' and t.school_id = s.school_id), (SELECT COUNT(*) FROM school_user t WHERE t.user_type = 'A' and t.school_id = s.school_id), (SELECT COUNT(*) FROM school_user t WHERE t.user_type = 'S' and t.school_id = s.school_id)) FROM school s inner join user u on s.user_created = u.user_id inner join plan p on s.current_plan = p.plan_Id where s.application_id = 30 and s.site_id = 42;
When I use this same query in my Dao method, I'm getting error like:
No Dialect mapping for JDBC type: 1111
Code used in dao method:
public List<Object[]> getInformationValues(int applicationId, int siteId) throws HibernateException {
Session session = getCurrentSession();
Query query = session.createSQLQuery("SELECT (s.school_id, u.first_name, u.last_name, u.username, u.email, p.plan_name, s.start_date, s.end_date, s.subscription_price, (SELECT COUNT(*) FROM school_user t WHERE t.user_type = 'T' and t.school_id = s.school_id), (SELECT COUNT(*) FROM school_user t WHERE t.user_type = 'A' and t.school_id = s.school_id), (SELECT COUNT(*) FROM school_user t WHERE t.user_type = 'S' and t.school_id = s.school_id)) FROM school s inner join user u on (s.user_created = u.user_id) inner join plan p on (s.current_plan = p.plan_Id) where s.application_id = :applicationId and s.site_id = :siteId") .setParameter("applicationId", applicationId) .setParameter("siteId", siteId);
List<Object[]> results = query.list();
return results;
}
Is there any way to fix this issue?

Spring Data JPA #Query annotation, nativeQuery = true,

I have problem with my #Repository:
#Repository
public interface RekvZmRepository extends CrudRepository<RekvalZamestn, RekvalZamestnPk> {
#Query(value = "SELECT z.* FROM rek_zm d INNER JOIN proj_a a ON d.id = a.prj_idcislo"
+ " INNER JOIN proj_e e ON a.id = e.id"
+ " INNER JOIN rekv_z z ON d.id = z.id"
+ "WHERE d.id = ?1 AND a.id = ?2 AND e.id = ?3", nativeQuery = true)
public List<RekvalZamestn> getRekvOsOnDoh(Long dhzmrk, Long prj, Long prje);
}
When I run it, result is:
org.springframework.dao.InvalidDataAccessResourceUsageException: could not
extract ResultSet; SQL [n/a]; nested exception is
org.hibernate.exception.SQLGrammarException: could not extract ResultSet
When I run SQL it works, so for me it looks like problem is not with SQL but with my #Query.
Your query, in one-line format (condensing multiple spaces to one space for reasons of, erm, space), equates to
SELECT z.* FROM rek_zm d INNER JOIN proj_a a ON d.id = a.prj_idcislo INNER JOIN proj_e e ON a.id = e.id INNER JOIN rekv_z z ON d.id = z.idWHERE d.id = ?1 AND a.id = ?2 AND e.id = ?3
If you concatenate all the strings in one line like this, it becomes obvious that you are missing a space before the WHERE clause.
change SELECT z.* FROM to SELECT z FROM assuming RekvalZamestn class maps to table rekv_z.

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();

Sub-queries in associations with hibernate

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

Categories