unexpected token error while running PostgreSQL query in Java - java

I have created the following query for PostgreSQL which is working fine in SqlWorkbench. But when I integrated this in Java code, I'm getting a syntax error exception:
Query running fine in SqlWorkbench:
ELECT poaiF.fnsku,
poaiF.acknowledgement_type_code AS last_ack_code
FROM po_acknowledgement_items poaiF,
(SELECT Max(poa.po_acknowledgement_id) AS last_po_ack_id,
poai.fnsku
FROM po_acknowledgement_items poai,
po_acknowledgements poa
WHERE poa.po_acknowledgement_id = poai.po_acknowledgement_id
AND poa.order_id = '5D7P2FLB'
GROUP BY poai.fnsku) t
WHERE t.last_po_ack_id = poaiF.po_acknowledgement_id
AND t.fnsku = poaiF.fnsku
Query in java (giving syntax error in beginning of (SELECT Max(poa.po_acknowledgement_id) AS last_po_ack_id):
private static final String LAST_ACK_CODE_QUERY1 = "SELECT poaiF.fnsku, \n" +
" poaiF.acknowledgement_type_code AS last_ack_code \n" +
"FROM po_acknowledgement_items poaiF, \n" +
" (SELECT Max(poa.po_acknowledgement_id) AS last_po_ack_id, \n" +
" poai.fnsku \n" +
" FROM po_acknowledgement_items poai, \n" +
" po_acknowledgements poa \n" +
" WHERE poa.po_acknowledgement_id = poai.po_acknowledgement_id \n" +
" AND poa.order_id = \'5D7P2FLB\' \n" +
" GROUP BY poai.fnsku) t \n" +
"WHERE t.last_po_ack_id = poaiF.po_acknowledgement_id \n" +
" AND t.fnsku = poaiF.fnsku";
While running the query through the integration test, getting the following error:
unexpected token: ( near line 4, column 8 which is the beginning of
(SELECT Max(poa.po_acknowledgement_id)
I am running through org.springframework.orm.hibernate3.LocalSessionFactoryBean which is as follows.
SessionFactory postgresSessionFactory; //initialized with org.springframework.orm.hibernate3.LocalSessionFactoryBean class.
final Session session = postgresSessionFactory.getCurrentSession();
String query = LAST_ACK_CODE_QUERY;
final Query selectQuery = session.createQuery(query).setTimeout(queryTimeout);
final List<Object[]> terms = selectQuery.list();
Please help me to resolve this issue.

From Hibernate documentation:
Query createQuery(String queryString)
Create a Query instance for the given HQL query string.
If you want a SQL query, you need to use createSQLQuery instead:
SQLQuery createSQLQuery(String queryString)
Create a SQLQuery instance for the given SQL query string.

Related

Spring JPA Query is not recognizing Spatial Types

I'm trying to make a native query request through spring JPA Query annotation using Spacial data types.
The query works perfectly when asked to execute through the console or even in the database.
But when he is asked to be used through Spring.
Does anyone know what I'm doing wrong? or there is a better way to achieve the same result (leaving all the calculations DB sided)?
Thank you in advance
This is the query I'm trying to execute. Again, it works through console but fails to execute through spring boot request
#Query(value = "SELECT TOP 1 * FROM Vehicles v " +
"JOIN Bikelots l ON l.BikeLotId = v.BikeLotId " +
"JOIN BikeTypes b ON b.BikeTypeId = l.BikeTypeId " +
"WHERE b.BikeTypeId = ?1 " +
"ORDER BY " +
"Geography::STGeomFromText(v.Point.MakeValid().STAsText(),4326) " +
".STDistance(Geography::STGeomFromText(Geometry::Point(?2,?3,4326).MakeValid().STAsText(),4326)) "
, nativeQuery = true)
com.microsoft.sqlserver.jdbc.SQLServerException: Incorrect syntax near 'Geography:'.
Im using this dialect in application.properties
spring.jpa.database-platform=org.hibernate.spatial.dialect.sqlserver.SqlServer2008SpatialDialect
The given error was caused because jpa hibernate recognizes the character ":" as a placeholder for an upcoming variable.
By placing the query in a String variable, then adding "\\" before each ":" and assigning the string to the value of #Query, solved the problem. See code for example
String query = "SELECT TOP 1 * FROM Vehicles v " +
"JOIN Bikelots l ON l.BikeLotId = v.BikeLotId " +
"JOIN BikeTypes b ON b.BikeTypeId = l.BikeTypeId " +
"WHERE b.BikeTypeId = ?1 " +
"ORDER BY " +
"Geography\\:\\:STGeomFromText(v.Point.MakeValid().STAsText(),4326) " +
".STDistance(Geography\\:\\:STGeomFromText(Geometry\\:\\:Point(?2,?3,4326).MakeValid().STAsText(),4326)) ";
#Query(value = query, nativeQuery = true)

org.postgresql.util.PSQLException: ERROR: syntax error at or near ":"

I am running an SQL query from PgAdmin4 which runs successfully, but when i take that same query to run it from my Spring Boot application i have an error " org.postgresql.util.PSQLException: ERROR: syntax error at or near ":" "
Here is what the SQL query looks like:
SELECT
student.surname, student.first_name, student.last_name,
jsonb_pretty(elems)
FROM assessment, jsonb_array_elements(assessment.assessment) AS elems
JOIN student ON student.id = (elems->>'student_id')::uuid
WHERE subject_id = 2
AND academy_year_id =3
AND form_id = 2
AND term_id = 1
AND section_id = 4;
And this run successfully from PgAdmin4.
This is my implementation in my Repository
#Query(nativeQuery = true, value = "SELECT\n" +
" student.surname, student.first_name, student.last_name,\n" +
" jsonb_pretty(elems)\n" +
"FROM assessment, jsonb_array_elements(assessment.assessment) AS elems\n" +
"JOIN student ON student.id = (elems->>'student_id')::uuid\n" +
"WHERE subject_id = 2\n" +
"AND academy_year_id =3\n" +
"AND form_id = 2\n" +
" AND term_id = 1\n" +
"AND section_id = 4;")
Object[] getSubjectAssessments();
And when my API calls this method i get this error message
org.postgresql.util.PSQLException: ERROR: syntax error at or near ":"
I don't know what I am doing wrong.
JPA can't handle the Postgres specific cast operator ::.
Use cast() instead:
JOIN student ON student.id = cast(elems->>'student_id' as uuid)

Join Query for unrelated entities in Spring boot JPA

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

Pass email as a parameter for SQL query, PostreSQL, JAVA

I'm trying to pass the email as a parameter for the SELECT SQL query in my JAVA back-end.
As i understood, for some reason it pass only "email_name" from the "email_name#email.com". (Getting this error):
Threw a SQLException creating the list of blogs.
ERROR: column "email_name" does not exist
Position: 174
There is an existed rows, which contains "email_name#email.com".
(Why "ERROR: column"? according to query it should look for a value, no?)
Here is My query:
String active_user = "email_name#email.com"; //email_name#email.com - example, active_user receive some path variable and on this particular moment(before query execution) contains exactly "email_name#email.com".
ResultSet rs = st.executeQuery("SELECT \n" +
" goods.item_title, \n" +
" goods.item_descr, \n" +
" goods.item_email,\n" +
" goods.item_images,\n" +
" goods.item_phone, \n" +
" goods.item_price \n" +
"FROM \n" +
" public.goods\n" +
"WHERE goods.owner = "+active_user+"\n" +
"ORDER BY\n" +
" goods.item_id ASC;");
So the question is - how to pass full email to query?
Try using String active_user = "'email_name#email.com'";. with single quotes. Since postgre recognized as column when you use double quotes.
You should use PreparedStatement. this is a example
Very unsafe approach, you should use PreparedStatement to avoid SQL injection. Here is existing answer

Avoid query duplication when 'IN list' which empty and non empty list

public static final String UPDATE_DOCUMENTS_WITH_TO_DELETE_FLAG_FOR_USER_SQL = "\n" +
"UPDATE document d \n" +
"SET d.indexed = :flagValue \n" +
"WHERE d.user_id = :userId \n" +
"AND d.to_delete = :toDelete";
public static final String UPDATE_DOCUMENTS_WITH_TO_DELETE_FLAG_FOR_USER_WITH_EXCEPTIONS_SQL = "\n" +
"UPDATE document d \n" +
"SET d.indexed = :flagValue \n" +
"WHERE d.user_id = :userId \n" +
"AND d.to_delete = :toDelete \n" +
"AND d.id NOT IN (:exceptForDocuments)";
public int markUserDocumentsToDeleteAsUnindexed(String userId,Collection<String> exceptForDocuments) {
Map<String,Object> params = Maps.newHashMap();
params.put("flagValue",false);
params.put("userId",userId);
params.put("toDelete",1);
params.put("exceptForDocuments",exceptForDocuments);
if ( exceptForDocuments.isEmpty() ) {
return jdbcTemplate.update(UPDATE_DOCUMENTS_WITH_TO_DELETE_FLAG_FOR_USER_SQL, params);
}
else {
return jdbcTemplate.update(UPDATE_DOCUMENTS_WITH_TO_DELETE_FLAG_FOR_USER_WITH_EXCEPTIONS_SQL,params);
}
}
Is there a way to use a single query to perform both updates?
Because actually using the UPDATE_DOCUMENTS_WITH_TO_DELETE_FLAG_FOR_USER_WITH_EXCEPTIONS_SQL query seems to work against H2, but not MySQL.
Any idea to avoid this query duplication?
The problem is likely because not every driver can handle parameterized arrays/collections. If you have complete control over the exceptForDocuments contents, you can serialize it to SQL yourself (with simple sanitization checks) and then conditionally append it without using parameters.

Categories