native query unable to set parameter while creating partition - java

I have the following query to create a partition, it's working with hardcoded values but is unable to replace parameters dynamically.
#Modifying
#Query(value = "CREATE TABLE :name PARTITION OF sample_table\n"
+ "FOR VALUES FROM (a) TO (b)", nativeQuery = true)
void createPartition(#Param("name") String name, #Param("a") long a, #Param("b") long b);
This statement I want to generate which is working fine on postgres console:
CREATE TABLE sample_table_p1 PARTITION OF sample_table
FOR VALUES FROM ('1020000') TO ('2000000');
error:
org.postgresql.util.PSQLException: ERROR: syntax error at or near "$1"
Thanks in advance :)

Related

Why does JPA give me a syntax error at or near?

I am learning spring-boot and I have a connection to a database, I am trying to perform the following query.
#Query(value = "select f.entity_id as 'NIT' from renting.fine f where f.companyparent = :companyParent", nativeQuery = true)
But it generates the following error about the value that starts with a single quote, I can't get it to recognize the value
org.postgresql.util.PSQLException: ERROR: syntax error at or near "'NIT'"
Remove single quotes around 'NIT'. In order to define aliases for column you don't require quotes at all.
#Query(value = "select f.entity_id as NIT from renting.fine f where f.companyparent = :companyParent", nativeQuery = true)
This should work.

Spring boot JPA nativeQuery Incorrect syntax near #P0

I am trying to run the following query from a spring boot app using Hibernate, and the problem is that in the query I need to pass the path variable from the method.
#Query(
value = "INSERT INTO dbo.images (imageblob)(SELECT * FROM OPENROWSET (BULK ?, SINGLE_BLOB) imageblol) SELECT CAST(scope_identity() AS int);",
nativeQuery = true)
Integer insertImage(String path);
the error I am getting is
com.microsoft.sqlserver.jdbc.SQLServerException: Incorrect syntax near '#P0'.
If I write the path manually it will work
#Query(
value = "INSERT INTO dbo.images (imageblob)(SELECT * FROM OPENROWSET (BULK 'C:\\pic\\NORMAL2-IM-1257-0001.jpeg', SINGLE_BLOB) imageblol) SELECT CAST(scope_identity() AS int);",
nativeQuery = true)
Integer insertImage(String path);
'#P0' is your RowCountToDisplay parameter ... Maybe try to place parenthesis around the argument
INSERT INTO dbo.images (imageblob)(SELECT * FROM OPENROWSET (BULK (?), SINGLE_BLOB) imageblol) SELECT CAST(scope_identity() AS int);"
, nativeQuery = true)

Order by clause query in Spring MVC with MapSqlParameterSource

I am trying to a SQL query in Spring MVC 4 with order by clause. But it does not work. I am using MapSQLParameterSource class to define sql parameters.
MapSqlParameterSource params = new MapSqlParameterSource();
params.addValue("lowerLimit", lowerLimit);
params.addValue("upperLimit", upperLimit);
params.addValue("filter", filter.trim()+"%");
params.addValue("order", order);
String sql = "SELECT * FROM tbl_Subject WHERE subjectName LIKE :filter ORDER BY :order limit :lowerLimit, :upperLimit";
It does not work actually. does not order any columns. When I try to hard coded it works fine as aspect.
String sql = "SELECT * FROM tbl_Subject WHERE subjectName LIKE :filter ORDER BY subjectId DESC limit :lowerLimit, :upperLimit";
How to I Order by clause query with MapSqlParameterSource.
The problem is in this line :
params.addValue("order", order);//consider this return col_name
This will be translate it to :
.. ORDER BY 'col_name' limit ..
^ ^
and this is a wrong syntax, logically after ORDER BY you have to pass a column name and not a value.
.. ORDER BY col_name limit ..
^^^^^^^^
Instead you have to pass it to the query directly but be carfull to pass the correct name, this can cause Syntax error or SQL Injection if you pass a wrong input

JPA EclipseLink - Get multiple objects by primary key maintaining order

I'm using EclipseLink as JPA implementation and I need to get multiple objects using the primary key (numeric id). But I also need to maintain the given id order.
Using native mySQL this kind of behaviour can be obtained using ORDER BY FIELD
SELECT id FROM table WHERE id IN(9,5,2,6) ORDER BY FIELD(id,9,5,2,6);
I'm now trying to replicate this query using JPA implementation. As already established from this thread, the ORDER BY FIELD is not supported, so I went to a more low-level approach using a JPA native query.
I'm try to reach this goal using a parameter query, instead of using a raw statement. The first implementation was like this
Class<?> clazz = ...;
List<Long> ids = ...;
EntityManagerFactory emf = ...;
EntityManager em = emf.createEntityManager();
String statement = "SELECT * FROM table WHERE id IN (?)";
Query createNativeQuery = em.createNativeQuery(statement, clazz);
createNativeQuery.setParameter(1, ids);
List resultList = createNativeQuery.getResultList();
As you can see the ORDER clause is not there yet, for the first step I just trying to make the parameter query work using the ids list with the IN operator. In the setParameter method I tried to provide the List object, a comma separated list (as string) but none of them works. At the end they all finish with a sql syntax error.
I also tried to play with the parenthesis, with or without, but nothing works.
Here some test I made
String statement = "SELECT * FROM " + tableName + " WHERE id IN (?)";
Query createNativeQuery = emJpa.createNativeQuery(statement, this.em.getClassObject());
createNativeQuery.setParameter(1, ids);
The query does not give any error, but no results given.
String statement = "SELECT * FROM " + tableName + " WHERE id IN (?)";
Query createNativeQuery = emJpa.createNativeQuery(statement, this.em.getClassObject());
createNativeQuery.setParameter(1, Joiner.on(",").join(ids));
Only one result is given, but 7 ids was provided to the query
From this topic I also tried using ?1 instead of ?, but no changes. Is there a way to make the nativeQuery working with a list of ids?
For the moment I'm using the full raw SQL statement
String joinedId = Joiner.on(",").join(ids);
String statement = "SELECT * FROM " + tableName + " WHERE id IN (" + joinedId + ") ORDER BY FIELD(id," + joinedId + ")";
Query createNativeQuery = emJpa.createNativeQuery(statement, this.em.getClassObject());
createNativeQuery.getResultList();
But at first I started with the parameter query for optimization and performance related of parsing each time the statement.
EDIT
With the suggestion of Chris I tried a TypedQuery using the FUNCTION operator (which is available because I'm using the latest EclipseLink). Here is the resulting code
List<Long> ids = ...;
Class<?> clazz = ...;
String statement = "SELECT e FROM " + clazz.getSimpleName() + " e WHERE e.id IN (:idList) ORDER BY FUNCTION('FIELD', e.id, :idList)";
EntityManagerFactory emf = ...;
EntityManager em = emf.createEntityManager();
TypedQuery<?> query = em.createQuery(statement, clazz);
query.setParameter("idList", ids);
List resultList = query.getResultList();
And here is the error while executing this code
Local Exception Stack:
Exception [EclipseLink-4002] (Eclipse Persistence Services - 2.6.3.v20160428-59c81c5): org.eclipse.persistence.exceptions.DatabaseException
Internal Exception: java.sql.SQLException: Operand should contain 1 column(s)
Error Code: 1241
Call: SELECT ... all the fields ... FROM webcontent_type WHERE (ID IN ((?,?,?,?,?,?,?))) ORDER BY FIELD(ID, (?,?,?,?,?,?,?))
bind => [14 parameters bound]
Query: ReadAllQuery(referenceClass=WebContentType sql="SELECT ... all the fields ... FROM webcontent_type WHERE (ID IN (?)) ORDER BY FIELD(ID, ?)")
EDIT 2
Tried without the parenthesis but there is still an error
SELECT e FROM FrameWorkUser e WHERE e.id IN :idList ORDER BY FUNCTION('FIELD', e.id, :idList)
I must say that with a list of one element the code works, but with another list of 10 elements there is an error
javax.persistence.PersistenceException: Exception [EclipseLink-4002] (Eclipse Persistence Services - 2.6.3.v20160428-59c81c5): org.eclipse.persistence.exceptions.DatabaseException
Internal Exception: java.sql.SQLException: Operand should contain 1 column(s)
Error Code: 1241
Call: SELECT .... FROM webcontent_type WHERE (ID IN (?,?,?,?,?,?,?)) ORDER BY FIELD(ID, (?,?,?,?,?,?,?))
bind => [14 parameters bound]
Query: ReadAllQuery(referenceClass=WebContentType sql="SELECT .... FROM webcontent_type WHERE (ID IN ?) ORDER BY FIELD(ID, ?)")
at org.eclipse.persistence.internal.jpa.QueryImpl.getDetailedException(QueryImpl.java:382)
at org.eclipse.persistence.internal.jpa.QueryImpl.executeReadQuery(QueryImpl.java:260)
at org.eclipse.persistence.internal.jpa.QueryImpl.getResultList(QueryImpl.java:473)
It seems that even w/o the parenthesis, the resulting statement has them
If you are going to use a native query, you must do it exactly like you would form the SQL for your database - this means you must break the list into its component parameters as JPA providers are not expected to change the SQL for you. Most providers handle lists in JPQL though, so "select e from Entity e where e.id in (:idList)" will work in EclipseLink.
Your missing bit is that 'FIELD' is not a JPQL construct. For this, you would have to use the JPQL 2.1 FUNCTION operator. Something like:
"Select e from Entity e where e.id in :idList order by FUNCTION('FIELD', e.id, :idList)"

Query using alias on column give an error

When i use alias for column i get error. Without alias everytinig works good. What is the problem with that ? This is simple example, but need to use more aliases in real project to wrap results in some not-entity class, but can't because of this error. How to solve this ?
NOT WORKING (with alias on id column):
public List<Long> findAll(Long ownerId) {
String sql = "select id as myId from products where ownerId = "+ownerId;
SQLQuery query = getSession().createSQLQuery(sql);
return query.list();
}
Error:
WARN [JDBCExceptionReporter:77] : SQL Error: 0, SQLState: S0022 ERROR
[JDBCExceptionReporter:78] : Column 'id' not found.
WORKING (without alias):
public List<Long> findAll(Long ownerId) {
String sql = "select id from products where ownerId = "+ownerId;
SQLQuery query = getSession().createSQLQuery(sql);
return query.list();
}
If your "product" is mapped, hibernate probably don't know about "myId" and therefore can't select it.
You can try something like:
getSession().createSQLQuery(sql).addScalar("myId", Hibernate.LONG)

Categories

Resources