I'm using Spring Data JPA. Could someone say, how to fix this error: "java.sql.SQLSyntaxErrorException: Unknown column 's' in 'field list'" while executing this simple request. "s" is alias for session table. I shortened the query.
#Query(value =
"SELECT l.name as lName, c.id as clientId, c.name as clientName, s.id as sessionId, a.ss_id as ssId, " +
"u.first_name as firstName, u.last_name as lastName, s.start_date as startDate, s.end_date as endDate, " +
"sc.version as version " +
"FROM session as s " +
"join scenario sc on sc.id = s.scenario_id " +
.........
"left join client c on c.id = p.client_id " +
"WHERE s.status = 'COMPLETED' " +
"and (s.record_rejected IS NULL OR s.record_rejected = 0) " +
"and sfe.id IS NULL " +
.........
"and s.end_date between :startDate and :endDate",
nativeQuery = true)
Page<DataItem> findData(Pageable pageable, #Param("startDate") LocalDateTime startDate, #Param("endDate") LocalDateTime endDate, .......);
}
In log I see the reason of the problem, after my main request spring data executes count request for Pageable object and this request starts with: select count(s) FROM session as s, but this is wrong. You can see it below in the text:
Hibernate: SELECT l.name as lName....
Hibernate: select count(s) FROM session as s ....
2022-02-24 22:10:51.864 WARN [app,363fdd7d5edaa51c,175b13cac216908e,true] 1 --- [nio-8082-exec-3] o.h.engine.jdbc.spi.SqlExceptionHelper : SQL Error: 1054, SQLState: 42S22
2022-02-24 22:10:51.864 ERROR [app,363fdd7d5edaa51c,175b13cac216908e,true] 1 --- [nio-8082-exec-3] o.h.engine.jdbc.spi.SqlExceptionHelper : Unknown column 's' in 'field list'
on the second line framework tries execute select count(s), but s is an alias for the table session. And this happens only when required size is less than totalElements, if not, then request is success.
DataItem is an interface projection.
What's wrong? Why framework tries to use table alias inside count() function?
I've tried to use countQuery argument in #Query annotation, but it didn't help.
Related
I have this sql query that works fine
SELECT ppd.userId, AVG(Coalesce(sm.score, 0)) AS avgScore
FROM Table1 ppd
LEFT JOIN Table2 sm ON ppd.userId = sm.userId AND sm.created BETWEEN start AND end
WHERE ppd.someId IN (listOfIds)
GROUP BY ppd.userId ORDER BY avgScore DESC LIMIT 1 OFFSET 0;
I have written a query for a method in a JPARepository that looks like the following
#Query(value = "SELECT ppd.userId, AVG(Coalesce(sm.score, 0)) AS avgScore " +
" FROM Table1 ppd " +
" LEFT JOIN Table2 sm ON sm.userId = ppd.userId AND sm.created BETWEEN :start AND :end " +
" WHERE ppd.someId IN (:IdList) GROUP BY ppd.userId",
nativeQuery = true)
Page<MyDtoProjection> getAvg(#Param("IdList") List<String> IdList,
#Param("start") Long start,
#Param("end") Long end,
Pageable pageable);
Which works just as expected except when the pageable size is 1 (SQL query with Limit 1 works fine).
For the pageable parameter the service sends the following pageable object
Sort sort = JpaSort.unsafe(Sort.Direction.ASC, "(avgScore)");
Pageable pageable = PageRequest.of(offset, limit, sort);
The request sets offset=0 and limit=1
The error I'm receiving from request using repository code is this one:
Unknown column 'ppd' in 'field list'\nQuery is: select count(ppd)..., I don't know why it is taking the alias ppd as a column name, also, I read from another post that this way of executing native queries performs a count (which can be seen in the error message, I did not specify that count query), and that it can be specified by setting countQuery parameter, but I'm not sure what to write there.
Solve it>
Just added the countQuery to the #Query annotation, I was not so sure what to place there, but it was simple
#Query(value = "SELECT ppd.userId, AVG(Coalesce(sm.score, 0)) AS avgScore " +
" FROM Table1 ppd " +
" LEFT JOIN Table2 sm ON sm.userId = ppd.userId AND sm.created BETWEEN :start AND :end " +
" WHERE ppd.someId IN (:IdList) GROUP BY ppd.userId",
countQuery = "SELECT COUNT(ppd.userId) FROM Table1 ppd " +
"WHERE ppd.userId IN (:IdList) GROUP BY ppd.userId",
nativeQuery = true)
Page<MyDtoProjection> getAvg(#Param("IdList") List<String> IdList,
#Param("start") Long start,
#Param("end") Long end,
Pageable pageable);
This is the only post I found that mentions the countQuery and how it works in one of the answers, go check it out if someone is going through the same
Spring Data and Native Query with pagination
I want to write a JPA query that extracts all my entities matching a simple condition (column=boolean value) and a more complex conditions, i.e. the entity ID shall be contained in another table. MyEntity has no relationship with this other table.
My not working guess is:
#Query(value =
"select msr " +
"from MyEntity msr " +
"where msr.archived=false " +
" AND msr.id in
(select sc.res from search_campaign_results sc
where search_campaign_id=:campaign)")
Page<MyEntity> findResultsNotAnalyzed(Pageable pr, #Param("campaign") Long campaign);
Of course the error is "search_campaign_results is not mapped", which is correct .
How can I fix this without writing a completely native query?
I'm having trouble getting the total count of the "one" side of a one-to-many join query in hibernate HQL / JPQL.
The two tables I'm attempting to join (which I don't control and cannot change) look something like this:
House:
PK FK: owner_id
PK: town
PK: state
PK FK: inspection_id
Car:
PK FK: owner_id
PK: town
PK: state
PK: vin
An owner can own many houses and many cars, but a car can be garaged in only one home. So the relationship between house and car is one to many. And the query I'm attempting to run looks like this
entityManager.createQuery(
"select count(distinct h) " + // also tried "select count(*)", but that counts cars per garage for some reason.
"from House h, Car c " +
"where h.owner.id = c.owner.id " +
"and h.town = c.town " +
"and h.state = c.state " +
"and h.inspection_id between 1 and 10 " +
"and c.vin between 12345 and 23456 " +
"group by h, c",
Long.class).getSingleResult().intValue();
But I'm getting an error when I try to run this query against my DB2 database. Apparently the distinct keyword doesn't work in db2. But am I doing this correctly? Is there another way to accomplish this with JPQL?
Why do I get a list of each houses car count when I replace "distinct h" with "*"?
Any help would be appreciated. Here's the exception I'm seeing:
11:13:56,753 WARN [org.hibernate.engine.jdbc.spi.SqlExceptionHelper] (batchProcessPool-1) SQL Error: -170, SQLState: 42605
11:13:56,754 ERROR [org.hibernate.engine.jdbc.spi.SqlExceptionHelper] (batchProcessPool-1) DB2 SQL Error: SQLCODE=-170, SQLSTATE=42605, SQLERRMC=COUNT, DRIVER=4.18.60
11:13:56,754 WARN [org.hibernate.engine.jdbc.spi.SqlExceptionHelper] (batchProcessPool-1) SQL Error: -516, SQLState: 26501
11:13:56,754 ERROR [org.hibernate.engine.jdbc.spi.SqlExceptionHelper] (batchProcessPool-1) DB2 SQL Error: SQLCODE=-516, SQLSTATE=26501, SQLERRMC=null, DRIVER=4.18.60
11:13:56,754 WARN [org.hibernate.engine.jdbc.spi.SqlExceptionHelper] (batchProcessPool-1) SQL Error: -514, SQLState: 26501
11:13:56,754 ERROR [org.hibernate.engine.jdbc.spi.SqlExceptionHelper] (batchProcessPool-1) DB2 SQL Error: SQLCODE=-514, SQLSTATE=26501, SQLERRMC=SQL_CURLN200C1, DRIVER=4.18.60
javax.persistence.PersistenceException: org.hibernate.exception.SQLGrammarException: could not extract ResultSet
...
EDIT
Thanks to #bowmore's suggestion, I revised the query to use the exists() function and it seems to be working! Thanks!
entityManager.createQuery(
"select count(h) " +
"from House h " +
"where h.inspection_id between 1 and 10 " +
"and exists (" +
"select c.vin from Car c " +
"where c.town = h.town " +
"and c.state = h.state " +
"and c.owner.id = h.owner.id " +
"and c.vin between 12345 and 23456)",
Long.class).getSingleResult().intValue();
I am trying to write a query like the below on unrelated entities A and B
Select a.x,a.y,a.z FROM A a ,B b Where
b.Parameter_Name='APPLICABLE_RULE_TYPE' And b.Parameter_KEY='MC' AND
b.Parameter_Value=a.rule_type And a.Rule_Status='ON' Order By Rule_Priority;
I am not able to figure out how this should be written in the Repository class of a Spring boot application.
Can someone please suggest a way do this
Thanks in advance.
Edit:
I have tried it as a native query like
#Query(value = "Select Rule_Id, Rule_Sql,S_System,S_Entity, s_table_name,Rule_Sql_Type "
+ "FROM rule_master TRM ,T_SYSTEM_CONFIG TSC Where"
+ " Tsc.Parameter_Name='APPLICABLE_RULE_TYPE' "
+ " And Tsc.Parameter_KEY= :systemType"
+ " AND Tsc.Parameter_Value=trm.rule_type "
+ " And Rule_Status='ON'"
+ " Order By Rule_Priority", nativeQuery = true)
public List<RuleMaster> findByRuleStatus(#Param("systemType" String systemType);
but getting this error
o.h.engine.jdbc.spi.SqlExceptionHelper : SQL Error: 17006, SQLState: null
o.h.engine.jdbc.spi.SqlExceptionHelper : Invalid column name
org.springframework.orm.jpa.JpaSystemException: could not execute query; nested exception is org.hibernate.exception.GenericJDBCException: could not execute query
I was able to solve this by using native query itself.
The error was because i was selecting only part of the columns from the table. Instead i have used the below query which works fine:
#Query(value = "Select * "
+ "FROM rule_master TRM ,T_SYSTEM_CONFIG TSC Where"
+ " Tsc.Parameter_Name='APPLICABLE_RULE_TYPE' "
+ " And Tsc.Parameter_KEY= :systemType"
+ " AND Tsc.Parameter_Value=trm.rule_type "
+ " And Rule_Status='ON'"
+ " Order By Rule_Priority", nativeQuery = true)
public List<RuleMaster> findByRuleStatus(#Param("systemType" String systemType);
I got this request :
TypedQuery<ParamGenerauxExternes> q = entityMgr
.createQuery("SELECT p FROM ParamGenerauxExternes p "
+ "WHERE EXISTS "
+ "(SELECT q FROM ParamGenerauxExternes q "
+ "WHERE q.key.origine = :pOrigine "
+ "AND q.key.typeParam LIKE :pTypeParametreBis "
+ "AND p.key.sousType LIKE CONCAT('%',q.libelleParam) "
+ "AND q.actif = 'Y') "
+ "ORDER BY p.libelleParam", ParamGenerauxExternes.class)
//.setParameter("pTypeParametre", "REL_TO_HOUSEHOLD")
.setParameter("pOrigine", pOrigineGrc)
.setParameter("pTypeParametreBis", "GRC_HOUSEHOLD_TYPE_P%");
But it doesn't work, I got this error message that tell a prenthesis is missing :
GRAVE: EJB Exception: : javax.persistence.PersistenceException: org.hibernate.exception.SQLGrammarException: ORA-00907: missing right parenthesis
The generated SQL by JPA has a parenthesis after the second select :
select
paramgener0_.CODE_PARAM as CODE1_2823_,
paramgener0_.ORIGINE as ORIGINE2823_,
paramgener0_.SOUS_TYPE as SOUS3_2823_,
paramgener0_.TYPE_PARAM as TYPE4_2823_,
paramgener0_.ACTIF as ACTIF2823_,
paramgener0_.LIBELLE_PARAM as LIBELLE6_2823_
from
FOA_PARAM_GEN_EXTERNE paramgener0_
where
exists (
select
(paramgener1_.CODE_PARAM,
paramgener1_.ORIGINE,
paramgener1_.SOUS_TYPE,
paramgener1_.TYPE_PARAM)
from
FOA_PARAM_GEN_EXTERNE paramgener1_
where
paramgener1_.ORIGINE=?
and (
paramgener1_.TYPE_PARAM like ?
)
and (
paramgener0_.SOUS_TYPE like '%'||paramgener1_.LIBELLE_PARAM
)
and paramgener1_.ACTIF='Y'
)
order by
paramgener0_.LIBELLE_PARAM
I don't know why hibernate add a parenthesis after the second select ? Please if you know what to do...
That query fails on Oracle but passes on, for example, Postgres. If you are using Oracle database, try setting Oracle SQL dialect to your JPA provider.
Hibernate SQL Dialects