Spring JPA row_to_json PostgreSQL - java

Instead of creating an entity with column annotation, is it possible to get query result with column name? Like:
#Query(value = "select emp.emp_id, emp_fname, emp_lname, emp_division_id, emp_role_id," +
"(select count(*) from cheers.ch_kudos where kudos_receiver_id = emp.emp_id) as received_kudos_num, " +
"(select count(*) from cheers.ch_kudos where kudos_sender_id = emp.emp_id) as sent_kudos_num " +
"from cheers.ch_employee as emp where emp.emp_active_flag = 'true'",
nativeQuery=true)
List<Object> getAllEmployeesReport();
The return result only has values, but doesn't have column name.
Otherwise, it there a way to get PostgreSQL row_to_json result by Spring JPA?
#Query(value = "select row_to_json(t) from (select emp.emp_id, emp_fname, emp_lname, emp_division_id, emp_role_id," +
"(select count(*) from cheers.ch_kudos where kudos_receiver_id = emp.emp_id) as received_kudos_num, " +
"(select count(*) from cheers.ch_kudos where kudos_sender_id = emp.emp_id) as sent_kudos_num " +
"from cheers.ch_employee as emp where emp.emp_active_flag = 'true') t",
nativeQuery=true)
List<Object> getAllEmployeesReport();
It will throw JDBC 111 exception.

Related

How to rewrite postgresSql query as Spring-data jpa query

I am stuck at the moment while trying to write the next query as a spring-data JPA query:
with recursive s as (
select *
from t
where file_id = '12345'
union all
select dfs.*
from t dfs
join s on s.file_id = dfs.parent_folder_id
)
select * from s;
I have tried the next:
#Query(value = "with recursive subfiles as (
select * from t where file_id=?1
union all
dfs.* from t dfs join subfiles s
on s.file_id = dfs.parent_folder_id)
select file_id from subfiles", nativeQuery = true)
But I get the next error:
Method threw 'org.springframework.dao.InvalidDataAccessResourceUsageException' exception.
could not extract ResultSet; SQL [n/a]
org.hibernate.exception.SQLGrammarException: could not extract ResultSet
org.postgresql.util.PSQLException: ERROR: syntax error at or near "dfs"
The query should list all direct or indirect dependent children for a specific id. (a similar post here)
I have managed to fix it using the next format:
#Query(nativeQuery = true,
value = "with recursive subfiles as " +
"(select * " +
"from t " +
"where file_id=?1 " +
"union all " +
"select dfs.* " +
"from t dfs " +
"join subfiles s " +
"on s.file_id = dfs.parent_folder_id) " +
"select file_id from subfiles")
List<String> listAllByParentId(String folderId);

JPA: ORDER BY before GROUP BY in JPARepository

This is the mysql query that I've:
SELECT * FROM (SELECT vev.* FROM vital_entry ve
INNER JOIN vital_entry_values vev ON ve.vital_entry_id=vev.vital_entry_id
WHERE ve.account_id=146
ORDER BY date_entered DESC) t1
GROUP BY vital_id ;
How do I do this in JPA?? I tried:
#Query("SELECT t1 FROM (SELECT ve FROM VitalEntry ve " +
"INNER JOIN ve.vitalEntryValues vev " +
"WHERE ve.accountId=:accountId " +
"ORDER BY ve.dateEntered DESC) t1")
List<VitalEntry> getRecentVitalValues(#Param("accountId") int accountId);
But IntelIj shows error expected identifer, got '('
This gave me the expected result
#Query("SELECT new com.v2.model.VitalValue(vev.vitalId, vev.value, max(ve.dateEntered), ve.vitalEntryType, vev.type) FROM VitalEntry ve " +
"INNER JOIN ve.vitalEntryValues vev " +
"WHERE ve.accountId=:accountId " +
"GROUP BY vev.vitalId " +
"ORDER BY max(ve.dateEntered) DESC")
List<VitalValue> getRecentVitalValues(#Param("accountId") int accountId);
Use native query instead:
#Query("SELECT * FROM (SELECT ve.* FROM vital_entry ve INNER JOIN vital_entry_values vev ON ve.vital_entry_id=vev.vital_entry_id WHERE ve.account_id=:accountId ORDER BY date_entered DESC) t1 GROUP BY vital_id", nativeQuery=true)
List<VitalEntry> getRecentVitalValues(#Param("accountId") int accountId);

hibernate native query variable

I am trying to write native query:
#NamedNativeQuery(name = "getUncheckedTests",
query = "SELECT t.test_name AS test_name, q.question AS question, #counter \\:= COUNT(ua.is_checked=0) AS uncheckedAnswers FROM user_answer ua" +
" JOIN result r on r.id = ua.result_id" +
" JOIN test t on r.test_id = t.id" +
" JOIN question q on ua.question_id = q.id" +
" WHERE r.is_checked = false AND q.is_open = true AND ua.is_checked = false" +
" AND r.test_id IN (SELECT t.id FROM result r" +
" JOIN test t on t.id = r.test_id" +
" JOIN user u on u.id = r.user_id" +
" WHERE r.permission = 2 AND u.id = :userId) and r.permission = 1 and #counter > 0" +
" GROUP BY ua.question_id")
However, i am getting empty result as #counter > 0 does not work properly. I can execute this query right in Workbench, however no result if it's put in Hibernate as native query
You should probably check the actual SQL Hibernate executes by enabling logging of the statements or by using log4jdbc and make sure you execute the query with the proper parameters.

Named Query to SELECT rows with MAX(column name), DISTINCT by another column

I have a case similar to the one described in this question, I wrote an identical query which works, but when I try to write it as a jpql named query, I'm getting an error.
My query:
#NamedQuery(
name = "findRankingsBetween",
query = "SELECT rt FROM Rankingtable rt " +
"INNER JOIN " +
"(SELECT teamId, MAX(lastupdate) as MaxDateTime " +
"FROM Rankingtable " +
"GROUP BY teamId) grouped " +
"ON rt.teamId = grouped.teamId " +
"AND rt.lastupdate = grouped.MaxDateTime " +
"WHERE rt.lastupdate BETWEEN :from AND :to"
)
Error:
Error in named query: findRankingsBetween: org.hibernate.hql.internal.ast.QuerySyntaxException: unexpected token: ( near line 1, column 79
How to write the query properly in jpql?
As noted in this answer, a subquery in JPQL can only occur in select and where clauses.
Hibernate doc.
An equivalent query in JPQL is:
"SELECT rt FROM Rankingtable rt " +
"WHERE rt.lastupdate = (SELECT MAX(r2.lastupdate) " +
"FROM Rankingtable r2 " +
"WHERE r2.teamid = rt.teamid) " +
"AND rt.lastupdate BETWEEN :from AND :to"

HQL query takes way too long to execute

I have this HQL query:
String hql = "from "+Patient.class.getName() + " p "
+ " where p.medicalRoom.id = "+medicalRoom.getId()
+ " and exists (select tg.id from "+TherapyGroup.class.getName()+" tg where tg.treatment.patient.id = p.id "
+ " and not exists (select ta.id from "+TherapyEnd.class.getName()+" ta where ta.therapyGroup.id = tg.id))";
All the properties that are involved in the query are indexed... Though it takes more than one whole minute to execute..

Categories