I got a syntax error when trying to call JPA function - java

When Im trying to call JPA function this statement I got an error: syntax error at or near ":"
public interface BcaTestRepository extends CrudRepository<InBodyBCA, Long> {
#Query(value = "SELECT * FROM in_body_bca bca WHERE person_id = :personId " +
"AND to_timestamp(bca.datetimes::text, 'YYYYMMDDHH24MISS') BETWEEN :startRange AND :endRange",
nativeQuery = true)
List<InBodyBCA> findAllByPersonId(#Param("personId") Long personId,
#Param("startRange") LocalDateTime startRange,
#Param("endRange") LocalDateTime endRange);
But in PgAdmin the query works fine
SELECT id, to_timestamp(datetimes::text, 'YYYYMMDDHH24MISS') as dt FROM in_body_bca WHERE to_date(datetimes::text, 'YYYYMMDDHH24MISS')
BETWEEN '2018-05-07' AND '2019-05-07' ORDER BY to_date(datetimes::text, 'YYYYMMDDHH24MISS') DESC ;

You use the double colon here: bca.datetimes::text. JPA would look for text variable name.
You need to escape it:
bca.datetimes\\:\\:text

Related

JPA parameter outside a where clause

I would like to know if the is a way to build a JPA query with parameter outside of the where clause. This query works fine in my database manager.
There is my query :
#Query(value = "SELECT q.quote, q.author, q.display_at, count(ql.*) AS like, (SELECT '{:userUUID}'::uuid[] && ARRAY_AGG(ql.user_uuid)::uuid[]) AS liked " +
"FROM quotes q " +
"LEFT JOIN quotes_likes ql ON ql.quote_uuid = q.uuid " +
"WHERE display_at = :date " +
"GROUP BY q.quote, q.author, q.display_at;", nativeQuery = true)
Optional<QuoteOfTheDay> getQuoteOfTheDay(UUID userUUID, LocalDate date);
I have the following error when the query is called : ERROR: syntax error at or near ":"
By default, Spring Data JPA uses position-based parameter binding. We can also use named parameter with #Param annotation to give a method parameter a concrete name and bind the name in the query. As you are trying to use the named parameter try using the below snippet with #Param annotations.
Optional<QuoteOfTheDay> getQuoteOfTheDay(#Param("userUUID") UUID userUUID, #Param("date") LocalDate date);
ERROR: syntax error at or near means that you need to escape casting colons.
Every : needs to be replaced by \\:
(SELECT ARRAY[:userUUID]'\\:\\:uuid[] && ARRAY_AGG(ql.user_uuid)\\:\\:uuid[]) AS liked
OR use double colons
(SELECT ARRAY[:userUUID]::::uuid[] && ARRAY_AGG(ql.user_uuid)::::uuid[]) AS liked
OR use Cast instead of colons
(SELECT cast(ARRAY[:userUUID] as uuid[]) && cast(ARRAY_AGG(ql.user_uuid) as uuid[])) AS liked
The second problem is that you need to create an array with a query parameter.
Try ARRAY[:userUUID] instead of {:userUUID}
Full query example:
#Query(value = "SELECT q.quote, q.author, q.display_at, count(ql.*) AS like, (SELECT ARRAY[:userUUID]\\:\\:uuid[] && ARRAY_AGG(ql.user_uuid)\\:\\:uuid[]) AS liked " +
"FROM quotes q " +
"LEFT JOIN quotes_likes ql ON ql.quote_uuid = q.uuid " +
"WHERE display_at = :date " +
"GROUP BY q.quote, q.author, q.display_at;", nativeQuery = true)
Optional<QuoteOfTheDay> getQuoteOfTheDay(UUID userUUID, LocalDate date);
As you are trying to pass method parameters to the query using named parameters, We define these using the #Param annotation inside our repository method declaration.
Each parameter annotated with #Param must have a value string matching the corresponding JPQL or SQL query parameter name.
#Query(value = "SELECT q.quote, q.author, q.display_at, count(ql.*) AS like, (SELECT '{:userUUID}'::uuid[] && ARRAY_AGG(ql.user_uuid)::uuid[]) AS liked " +
"FROM quotes q " +
"LEFT JOIN quotes_likes ql ON ql.quote_uuid = q.uuid " +
"WHERE display_at = :date " +
"GROUP BY q.quote, q.author, q.display_at;", nativeQuery = true)
Optional<QuoteOfTheDay> getQuoteOfTheDay(#Param("userUUID") UUID userUUID,#Param("date") LocalDate date);
Refer this for more details on how to use the #Query annotation.

Check if an integer is in a jsonb list

I'm trying to write a native query in JPA. I want to verify if an element exists in a jsonb column. However, I'm getting the error integer <# jsonb.
This is my query:
#Query(
value = "SELECT u FROM user u WHERE (u.depNum = ?1 and superAdmin = true " +
" and ?2 <# (u.listUsers)) ",
nativeQuery = true
)
public List<EbUser> selectSuperAdmin(Integer depNum, Integer userNum);
The error happens here: ?2 <# (u.listUsers). How can I verify that listUsers contains the userNum or how can I convert the userNum to jsonb in Java?
You can do the conversion in PostgreSQL.
and to_jsonb(ARRAY[?2]) <# (u.listUsers))
as long as JPA doesn't interfere with passing this construct into PostgreSQL, I have not tested that part.

Error org.hibernate.exception.SQLGrammarException: could not extract ResultSet

I have the hql query that I am executing but receive an error that I don't really understand the cause of.
This is my code:
#Override
public List<StaffRequest> getStaffLeaveRequest(String userID, Date startDate, Date endDate)
{
Session currentSession = sessionFactory.getCurrentSession();
List<StaffRequest> results =
currentSession.createQuery("select new com.timesheet_Webservice.CustomEntity.StaffRequest(lr.leave_ID, lr.leave_Employee, concat(s.staff_First_Name, ' ', s.staff_Last_Name), "
+ "(lr.leave_Days*8.5), lr.leave_Comments, '1805', concat(pro.project_Pastel_Prefix, ' - ', pro.project_Description), lr.leave_Start, lr.leave_End, lr.leave_IsApproved, "
+ "(select lt.leaveType_Description from LeaveType lt where lt.leaveType_ID = lr.leave_Type)) "
+ "from Staff s, Project pro, Leave lr "
+ "where lr.leave_Employee = s.staff_Code and pro.project_Code = 1805 and lr.leave_Approved = :userID and lr.leave_IsApproved = 0 and s.staff_IsEmployee <> 0 "
+ "and lr.leave_Start between :startDate and :endDate "
+ "order by concat(s.staff_First_Name, ' ', s.staff_Last_Name)")
.setParameter("userID",userID).setParameter("startDate", startDate).setParameter("endDate", endDate).getResultList();
return results;
}
I get this error on the webpage when trying to execute it:
org.hibernate.exception.SQLGrammarException: could not extract
ResultSet
And also this console error:
ERROR: You have an error in your SQL syntax; check the manual that
corresponds to your MariaDB server version for the right syntax to use
near 'Leave leave2_ where leave2_.Leave_Employee=staff0_.Staff_Code
and project1_.Proj' at line 1
It seems to indicate some fault at the where clause, but I don't see anything particularly wrong.
UPDATE:
Entity classes
Project
#Entity
#Table(name="project")
public class Project {
#Id
#GeneratedValue(strategy=GenerationType.IDENTITY)
#Column(name="Project_Code")
public int project_Code;
#Column(name="Project_Customer")
public int project_Customer;
//A lot more attributes...
}
Staff
#Entity
#Table(name="staff")
public class Staff
{
#Id
#Column(name="Staff_Code")
public String staff_Code;
...
}
1) As you using java.util.Date for Leave.leave_Start, you should annotate with proper #Temporal value:
#Temporal(TemporalType.TIMESTAMP)
#Column(name="Leave_Start")
Date leave_Start;
2) When setting your query date parameters, try using:
.setDate("startDate", startDate)
or
.setParameter("startDate", startDate, TemporalType.TIMESTAMP)
Ok, after much testing I discovered the reason for the error. For some unknown reason the query seems to have a problem with the name of the referenced table 'leave' and produces the error whenever I try to retrieve data from it. If I however rename the table to something as simple as 'leaves' then the query executes successfully. Anyone might know why this is?
Apparently JPA follows some rule or convention of variable names and does not accept "_" and for some reason does not accept intermediate capital letters... It worked for me by changing all variables to lowercase

Use postgres function timestamp in JpaRepository

I try to group by date only, column active_to is timestamp so it has time also. This query works in pgAdmin but JpaRepository seems to have problem even if it is native query. How can I modify this query to work using JpaRepository?
#Query(value = "SELECT o.active_to::timestamp::date, count(o) as sum from work_order o group by o.active_to::timestamp::date order by o.active_to::timestamp::date asc limit 7", nativeQuery = true)
I get this error:
org.postgresql.util.PSQLException: ERROR: syntax error at or near ":"
Position: 19
You cannot use : because this is the character that starts a named parameter.
You have to use cast.
#Query(value = "SELECT cast(cast(o.active_to as timestamp) as date), count(o) as sum " +
"from work_order o group by cast(cast(o.active_to as timestamp) as date) " +
"order by cast(cast(o.active_to as timestamp) as date) asc limit 7",
nativeQuery = true)
Cast and :: are similar. Read more about here:
https://www.postgresql.org/docs/current/sql-expressions.html#SQL-SYNTAX-TYPE-CASTS

Spring Boot: JPA QueryDSL: How to Make a Named Delete?

In the QueryDSL repository, I can make a named query in this way:
public interface HistoricalDataRepository
extends PagingAndSortingRepository<HistoricalData, Long>,
QueryDslPredicateExecutor<HistoricalData> {
List<HistoricalData> findAll(Predicate predicate);
HistoricalData findByKeyAndDate(String key, String date);
#Query(value = "SELECT * FROM historical_data h WHERE "
+ " h.key = :key "
+ " AND h.date <= :date "
+ " order by date desc"
+ " limit 1"
, nativeQuery = true)
HistoricalData myFindByKeyLowerOrEqualToDate(
#Param("key") String key
, #Param("date") Date date
);
How can I perform a
DELETE FROM HISTORICAL_DATA;
If I use the same syntax as above (with the #Queryannotation), I get an exception:
org.springframework.orm.jpa.JpaSystemException:
could not extract ResultSet; nested exception is
org.hibernate.exception.GenericJDBCException: could not extract ResultSet
Background: I do not want to use a
historicalDataRepository.deleteAll();
as this has a VERY low performance.
EDIT:
My syntax would look like the following:
#Query(value = "DELETE FROM HISTORICAL_DATA", nativeQuery = true)
void myDeleteAll();
Looks like, you are combining both JPA query as well as native query. For the syntax you have given, you have to specify it as native as shown below
#Query(value = "DELETE FROM HISTORICAL_DATA", nativeQuery = true)

Categories