why this strange behavior of OpenJpa? - java

why do this query works directly on postgres database:
select m from medicine_case m WHERE m.id IN (select m.id FROM medicine_case m LEFT OUTER JOIN patient ON m.patient=patient.id ORDER BY patient.surname ASC )
AND in OpenJpa with the exact corresponding typed query:
String sql = " select m from medicine_case m WHERE m.id IN (select m.id FROM medicine_case m LEFT OUTER JOIN "
+ "patient ON m.patient=patient.id ORDER BY patient.surname ASC )";
TypedQuery<MedicineCase> query = persistenceClient.createQueryMC(sql);
setParameter(query);
query.setFirstResult(first);
query.setMaxResults(count);
gives me:
org.apache.openjpa.persistence.ArgumentException: Encountered "m . id IN ( select m . id FROM medicine_case m LEFT OUTER JOIN patient ON" at character 37, but expected: ["(", ")", "*",.... etc etc
why????? it's so strange and makes me crazy!
the code that creates the query from entity manager:
return entityManager.createQuery(sql, MedicineCase.class);
and the code that executes it:
return query.getResultList().iterator();

You're confusing SQL (which is what PostgreSQL expects) and HQL (which is what EntityManager.createQuery() expects).
Those are two different languages. SQL works with tables and columns, whereas JPQL works with JPA entities, fields/properties and associations, and is translated by your JPA implementation into SQL.
If you want to execute SQL, you must use EntityManager.createNativeQuery().

in jpql it becomes a bit different:
String sql = "select m from " + MedicineCase.class.getSimpleName() + " m WHERE m.id IN :mcList";
TypedQuery<MedicineCase> query = persistenceClient.createQueryMC(sql);
query.setParameter("mcList", persistenceClient.executeQueryMCId(persistenceClient.createQueryMCId(createSql()
+ addOrders())));
setParameter(query);
query.setFirstResult(first);
query.setMaxResults(count);
return persistenceClient.executeQueryMC(query);
where createSql returns:
sql.append("select m.id ").append(" FROM ").append(MedicineCase.class.getSimpleName()).append(" m");
and addOrders:
" LEFT OUTER JOIN m.patient p ORDER BY p.surname ASC

Related

JPA unknown column alias in 'group statement'

I got an error while running this query on java SQL but it works when I tested it on SQL editor
#Query(value = "SELECT l.loan, max(i.date) as dDate, tr.collecty, sum(i.expectedAmount) as amount,"
+ "(select CASE WHEN (br.stype = 'x') THEN br.idNumber ELSE br.np END as type from Bower br inner join Leds ld on br.id = ld.bowerId where ld.loan = :loan) as bId "
+ "FROM Loan l INNER JOIN Inst i ON l.loan = i.loan INNER JOIN TList tr ON l.loan = tr.loan WHERE l.loan = :loan GROUP BY l.loanId, tr.collecty, bId")
and got error
Caused by: java.sql.SQLSyntaxErrorException: Unknown column 'bId' in 'group statement'
how to fix it?
The order of execution of group by is before the select in a query. So, at the time you group by bId, the select query is not executed yet and it won't recognize bId column or any alias that you specify at select.
Since bId is a derived column, you can not perform aggregation using the column at the same level. You need to go one level above. Below code should work. However there is still a scope to improve the way aggregation is being performed.
#Query(value = “SELECT loan, dDate, collecty, amount, bId FROM (SELECT l.loan, max(i.date) as dDate, tr.collecty, sum(i.expectedAmount) as amount,"
+ "(select CASE WHEN (br.stype = 'x') THEN br.idNumber ELSE br.np END as type from Bower br inner join Leds ld on br.id = ld.bowerId where ld.loan = :loan) as bId ) "
+ "FROM Loan l INNER JOIN Inst i ON l.loan = i.loan INNER JOIN TList tr ON l.loan = tr.loan WHERE l.loan = :loan ) GROUP BY loan, dDate, collecty, amount, bId”)

Java: SELECT query in INNER JOIN

Following SQL query works perfectly fine in Postgres. It returns all latest trainings of a given exercise.
SELECT th.id, th.date, th.exercise_id
FROM Training th
INNER JOIN (
SELECT exercise_id, MAX(date) AS maxdate
FROM Training
GROUP BY exercise_id
) AS tm ON tm.exercise_id = th.exercise_id AND th.date = tm.maxdate
The problem is that Java JPA fails with
java.lang.IllegalArgumentException: org.hibernate.hql.internal.ast.QuerySyntaxException unexpected token: (
after the INNER JOIN for the following code example.
String queryString = "SELECT th FROM TrainingHistory th INNER JOIN ( SELECT tm.exercise, MAX(date) as maxdate FROM TrainingHistory group by exercise ) AS tm on (tm.exercise = th.exercise AND th.date = tm.maxdate) WHERE th.accountId = 0";
What am I missing?

How to retrieve data and count of data at same time in hql?

I want to retrieve count and list of data in one query only which I want to write on JPA repository. I wrote it using a constructor and executed using entity manager, but it didn't work. It gave me a QuerySyntaxException. Here is my query:
String hql = "select new core.abc(select count(*) from abc as m where m.Id in :Ids and m.Type = :Type,"
+ "select max(m.modificationTime) from abc as m where m.Id in :Ids and m.Type = :Type )";
How can I write such kind of query in JPA repository?
I just figure out your use case senario is that you want to get all records from table as well as total-count of records and max value of a specific column , you named that column as modificationTime. So onething will be happen in this case, if you want to intract with table with single query, Than you will get useless data for both column named as max and count.
Try This for JPA,
#Query(value="SELECT cb from abc cd where cd.Id in (?1) and cd.Type=?2 , (SELECT MAX(m.modificationTime) as maxModificationTime , COUNT(*) as count FROM abc m where m.Id in (?3) and m.Type=?4) as m",nativeQuery=true)

Java JPA - Inner Join Query doesn't work

I'm currently having an issue using Java JPA with EclipseLink - this query:
SELECT VAR_INPUT.*
FROM VAR_INPUT
INNER JOIN TYPE_VAR_INPUT
ON VAR_INPUT.ID_TYPE_VAR_INPUT = TYPE_VAR_INPUT.ID_TYPE_VAR_INPUT
WHERE TYPE_VAR_INPUT.IS_MANDATORY_TYPE_VAR_INPUT=true;
is working fine when run directly on my database, but doesn't work when I use it with JPA.
JPA Query:
#NamedQuery(name = "VarInput.findAVarInputllOfMandatoryType",
query = "SELECT v "
+ "FROM VarInput v "
+ "INNER JOIN TypeVarInput t "
+ "ON v.ID_TYPE_VAR_INPUT = t.ID_TYPE_VAR_INPUT "
+ "WHERE t.isMandatoryTypeVarInput=:isMandatoryTypeVarInput"),
When I execute it in my Java application, I get the following error:
"The field [VAR_INPUT.ID_VAR_INPUT] in this expression has an invalid table in this context."
Exception in thread "AWT-EventQueue-0" Local Exception Stack:
Exception [EclipseLink-6069] (Eclipse Persistence Services - 2.5.2.v20140319-9ad6abd): org.eclipse.persistence.exceptions.QueryException
Exception Description: The field [VAR_INPUT.ID_VAR_INPUT] in this expression has an invalid table in this context.
Query: ReadAllQuery(name="VarInput.findAVarInputllOfMandatoryType" referenceClass=VarInput jpql="SELECT v FROM VarInput v INNER JOIN TypeVarInput t ON v.ID_TYPE_VAR_INPUT = t.ID_TYPE_VAR_INPUT WHERE t.isMandatoryTypeVarInput=:isMandatoryTypeVarInput")
at org.eclipse.persistence.exceptions.QueryException.invalidTableForFieldInExpression(QueryException.java:749) at org.eclipse.persistence.exceptions.QueryException.invalidTableForFieldInExpression(QueryException.java:749)
at org.eclipse.persistence.internal.expressions.FieldExpression.validateNode(FieldExpression.java:296)
My tables looks like that:
Table VAR_INPUT(ID_VAR_INPUT, NAME_VAR_INPUT, ID_TYPE_VAR_INPUT)
Table TYPE_VAR_INPUT(ID_TYPE_VAR_INPUT, NAME_TYPE_VAR_INPUT, IS_MANDATORY_VAR_INPUT)
"VAR_INPUT ManyToOne TYPE_VAR_INPUT"
Do you have any idea of why this happens?
NB: The Entities were generated by NetBeans
You don't use inner join in JQPL like that, you join on entity fields. I'm guessing now since you didn't provide entity code, but try this
#NamedQuery(name = "VarInput.findAVarInputllOfMandatoryType",
query = "SELECT v "
+ "FROM VarInput v "
+ "join v.type t "
+ "WHERE t.isMandatoryTypeVarInput=:isMandatoryTypeVarInput")
In this case you don't even need to join, you can simplify the query to this (inner join is implicitly used)
#NamedQuery(name = "VarInput.findAVarInputllOfMandatoryType",
query = "SELECT v "
+ "FROM VarInput v "
+ "WHERE v.type.isMandatoryTypeVarInput=:isMandatoryTypeVarInput")

Jpa namedquery with left join fetch

this is my namedquery:
#NamedQuery(
name = "User.findOneWithLists",
query = "SELECT u FROM User u "
+ "LEFT JOIN FETCH u.aTemplates "
+ "LEFT JOIN FETCH u.bTemplates "
+ "LEFT JOIN FETCH u.bp "
+ "LEFT JOIN FETCH u.aCredentials "
+ "LEFT JOIN FETCH u.st WHERE (st.deleted = false) "
+ "LEFT JOIN FETCH u.bCredentials "
+ "LEFT JOIN FETCH u.cl "
+ "WHERE u.id= :id")
My problem is that I get an error when the application starting:
org.hibernate.hql.internal.ast.QuerySyntaxException: unexpected token: LEFT ....
On the st side there is an annotation
#ManyToOne
#JoinColumn(name = "st_user")
private User user;
Any idea how can I handle this where clause?
Check a SQL syntax, you can't use left join after where clause. If you are looking at the SQL generated form that named query you will see that joined tables in the query the where clause comes after joins and should specify equal condition that links those tables by the keys. The primary key of the main table on the left and the foreign key of the joined table on the right. The joined table is specified by the property of your many-to-one association.
#NamedQuery(
name = "findOneWithLists",
query = "from Table t left join User u where u.id= :id"
)
For join conditions Hibernate provides the with keyword, even before JPA 2.1.
The relevant part of your query thus would look like this:
SELECT u FROM User u ... LEFT JOIN u.st WITH st.deleted = false
I'm not sure about LEFT JOIN FETCH u.cl with u.id= :id but if I remember correctly, that's not as easy and might have to be resolved with an adapted join and u.ui = :id in the where condition.
LEFT JOIN FETCH u.st WITH st.deleted = false`
This is not supported, since you can't do a partial fetch.

Categories

Resources