Parameterized sql in clause with variable number of arguments in DB2 - java

I have a sql as below in my java program:
String sql = "Select * from mySchema.myTable where product in (?) and myDate = ?";
I have my query params as:
Object[] params = {"\'abc\',\'pqr\',\'lmn\'",'2013-07-18'};
And I am trying to execute as:
List<Map<String, Object>> results = jdbcTemplate.queryForList(sql, params);
where jdbcTemplate is a org.springframework.jdbc.core.JdbcTemplate object.
However, I am getting error as:
org.springframework.dao.DataIntegrityViolationException: PreparedStatementCallback; SQL [Select * from mySchema.myTable where product in (?) and myDate = ?]; DB2 SQL Error: SQLCODE=-302, SQLSTATE=22001, SQLERRMC=null, DRIVER=3.59.81; nested exception is com.ibm.db2.jcc.am.SqlDataException: DB2 SQL Error: SQLCODE=-302, SQLSTATE=22001, SQLERRMC=null, DRIVER=3.59.81
at org.springframework.jdbc.support.SQLStateSQLExceptionTranslator.doTranslate(SQLStateSQLExceptionTranslator.java:101)
at org.springframework.jdbc.support.AbstractFallbackSQLExceptionTranslator.translate(AbstractFallbackSQLExceptionTranslator.java:72)
at org.springframework.jdbc.support.AbstractFallbackSQLExceptionTranslator.translate(AbstractFallbackSQLExceptionTranslator.java:80)
at org.springframework.jdbc.support.AbstractFallbackSQLExceptionTranslator.translate(AbstractFallbackSQLExceptionTranslator.java:80)
at org.springframework.jdbc.core.JdbcTemplate.execute(JdbcTemplate.java:602)
at org.springframework.jdbc.core.JdbcTemplate.query(JdbcTemplate.java:636)
at org.springframework.jdbc.core.JdbcTemplate.query(JdbcTemplate.java:665)
at org.springframework.jdbc.core.JdbcTemplate.query(JdbcTemplate.java:673)
at org.springframework.jdbc.core.JdbcTemplate.query(JdbcTemplate.java:713)
at org.springframework.jdbc.core.JdbcTemplate.queryForList(JdbcTemplate.java:796)
Further down the stack trace:
Caused by: com.ibm.db2.jcc.am.SqlDataException: DB2 SQL Error: SQLCODE=-302, SQLSTATE=22001, SQLERRMC=null, DRIVER=3.59.81
at com.ibm.db2.jcc.am.dd.a(dd.java:668)
at com.ibm.db2.jcc.am.dd.a(dd.java:60)
at com.ibm.db2.jcc.am.dd.a(dd.java:127)
at com.ibm.db2.jcc.am.bn.c(bn.java:2546)
at com.ibm.db2.jcc.am.bn.a(bn.java:2053)
at com.ibm.db2.jcc.t4.cb.n(cb.java:802)
at com.ibm.db2.jcc.t4.cb.i(cb.java:259)
at com.ibm.db2.jcc.t4.cb.c(cb.java:54)
at com.ibm.db2.jcc.t4.q.c(q.java:44)
at com.ibm.db2.jcc.t4.rb.j(rb.java:147)
at com.ibm.db2.jcc.am.bn.ib(bn.java:2048)
at com.ibm.db2.jcc.am.cn.b(cn.java:3845)
at com.ibm.db2.jcc.am.cn.b(cn.java:3975)
at com.ibm.db2.jcc.am.cn.bc(cn.java:678)
at com.ibm.db2.jcc.am.cn.executeQuery(cn.java:652)
at org.springframework.jdbc.core.JdbcTemplate$1.doInPreparedStatement(JdbcTemplate.java:643)
at org.springframework.jdbc.core.JdbcTemplate.execute(JdbcTemplate.java:586)
How can I pass a string as a parameter to my sql where my string is of type 'abc','pqr','xyz'
Thanks for reading!

I suggest you use a better ORM like MyBatis.
Also it looks like you're passing a string parameter as a date.
Your solution to pass a list of strings to IN statement won't work either, your
"'abc','cde'" will be treated as a single string in the IN statement since all SQL characters like , are ignored in parameters of parametrized statements (it's the feature that prevents SQL injection).

Related

SQLException pg_get_serial_sequence NOT FOUND

I am trying to do JUnit tests with H2, and my APP is configurated to work with PostgreSQL, and with ACL's Spring Boot.
So I have to add into the app the next two lines:
`mutableAclService.setClassIdentityQuery("select currval(pg_get_serial_sequence('acl_class', 'id'))");
mutableAclService.setSidIdentityQuery("select currval(pg_get_serial_sequence('acl_sid', 'id'))");`
to create the AclService.
I have in the application.properties the configuration (spring.datasource.url=jdbc:h2:~/test_db;MODE=PostgreSQL)
But it always returns me:
org.springframework.jdbc.UncategorizedSQLException: StatementCallback;
uncategorized SQLException for SQL [select
currval(pg_get_serial_sequence('acl_sid', 'id'))]; SQL state [90022];
error code [90022]; Function "PG_GET_SERIAL_SEQUENCE" not found; SQL
statement: select currval(pg_get_serial_sequence('acl_sid', 'id'))
[90022-197]; nested exception is org.h2.jdbc.JdbcSQLException:
Function "PG_GET_SERIAL_SEQUENCE" not found; SQL statement ...
Anyone knows how to fix it?
Replacing the
"select currval(pg_get_serial_sequence('acl_class', 'id'))"
for a SQL standard query
"SELECT CURRVAL(SELECT SEQUENCE_NAME FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 'acl_class' AND COLUMN_NAME = 'id')"
it works!

Error while creating SQL query with bind variables - JDBCTemplate in Spring

I am very beginner to Spring - JDBC .
I am trying to retrieve the employee_id from a table using the query having bind variables and also with IN condition in it .
I'm getting SQLException that
" invalid column type" - Caused by:
org.springframework.jdbc.UncategorizedSQLException:
PreparedStatementCallback; uncategorized SQLException for SQL [select
employee_id from table_employee where age=:varTwo and marks in
(:varOne) and name =:varThree]; SQL state [99999]; error code [17004];
Invalid column type; nested exception is java.sql.SQLException:
Invalid column type
Can you please tell , where I'm wrong .
I have tried using the types as Long , Integer , String but still i'm getting "invalid column type"
age is - NUMBER
marks is - NUMBER
name is - VARCHAR
MapSqlParameterSource parameters = new MapSqlParameterSource();
parameters.addValue("varOne", varOne);
parameters.addValue("varTwo", Long.parseLong(varTwo));
parameters.addValue("varThree", varThree);
Long employeeId = jdbcTemplate.queryForObject("select employee_id from table_employee where age=:varTwo and marks in (:varOne) and name =:varThree" , Long.class , parameters);
I should be getting the result of this SQL as the "employee id".
I think the type of varOne may be Collection.
When you want to use a variable in SQL query especially with IN, you should make sure the variable is a correct type.
Thanks for your responses. I was able to proceed further by making the list to string using join method.

Injecting JSON parameter in nativeQuery

This works when
#Query(
value = "SELECT * FROM person WHERE school = :schoolId AND details #> '{\"id\":\"1234\",\"name\":\"John\"}'",
nativeQuery = true
)
I am passing #Param("schoolId") String schoolId
But when I pass the JSON as a param, it fails with
org.springframework.dao.InvalidDataAccessResourceUsageException, could not extract ResultSet; SQL [n/a]; nested exception is
org.hibernate.exception.SQLGrammarException: could not extract ResultSet
org.postgresql.util.PSQLException: ERROR: operator does not exist: jsonb #> character varying
Hint: No operator matches the given name and argument type(s). You might need to add explicit type casts.
#Query(value = "SELECT * FROM person WHERE school = :schoolId AND details #> :details", nativeQuery = true)
#Param("schoolId") String schoolId, #Param("details") String details
Spring+JDBC binds Strings as VARCHAR by default. The cheap solution here is to use cast(s):
details #> CAST(:details AS jsonb)
But, if you have a lot of queries, in which some non-standard types are used as parameters & you want to bind their String representation, you can use the
stringtype=unspecified
JDBC DSN parameter in your connection string. That way, every parameter, which is bound by setString() will have an unknown type in PostgreSQL, thus it will try to infer their actual types.
Thanks for this.
Just in addition to the solution, you can also do the cast as:
details #> :details::jsonb
I'm using version 11 of postgres, not sure when it was introduced.

How to write Date range query in H2 using jooq

I'm using mybatis library to execute native sql queries.
I'm using jooq to generate dynamic sql queries for different dialects.
Syntax:
condition = condition.and(DSL.field("START_TIME_").between("2014-10-12")
.and("2014-10-12"));
Error:
org.apache.ibatis.exceptions.PersistenceException:
### Error querying database. Cause: org.h2.jdbc.JdbcSQLException: Syntax error in SQL statement "SELECT * FROM ACT_HI_PROCINST WHERE (DELETE_REASON_ IS NULL AND START_TIME_ BETWEEN CAST(:[*]1 AS VARCHAR) AND CAST(:2 AS VARCHAR))
LIMIT ? OFFSET ? "; expected "NOT, EXISTS, INTERSECTS, SELECT, FROM"; SQL statement:
select *
from ACT_HI_PROCINST
where (DELETE_REASON_ is null and START_TIME_ between cast(:1 as varchar) and cast(:2 as varchar))

springframework.jdbc.UncategorizedSQLException :Invalid column type-

Hi am trying to do a QueryForInt using spring jbdc.The query returns a simple count.On execution i get springframework.jdbc.UncategorizedSQLException:java.sql.SQLException: Invalid column type.
I did find similar posts and tried the suggestions but i am still stuck:(...
Any help is appreciated.
MapSqlParameterSource params = new MapSqlParameterSource();
params.addValue(DAOConstants.PROD_ID, custVo.getProdId(),OracleTypes.NUMBER);
params.addValue(DAOConstants.REQ_IND, DAOConstants.FLAG_Y,OracleTypes.VARCHAR);
The query:
select count(1) from prod where prod_id = :PROD_ID and req_ind =:REQ_IND
Table definition
Name Null Type
----------------- -------- ------------
PROD_ID NOT NULL NUMBER(5)
REQ_IND VARCHAR2(10)
The Logs..
Caused by: org.springframework.jdbc.UncategorizedSQLException: PreparedStatementCallback;
uncategorized SQLException for SQL [select count(1) from prod where prod_id = :PROD_ID and req_ind = :REQ_IND ]; SQL state [99999]; error code [17004]; Invalid column type; nested exception is java.sql.SQLException: Invalid column type
at org.springframework.jdbc.support.AbstractFallbackSQLExceptionTranslator.translate(AbstractFallbackSQLExceptionTranslator.java:83)
at org.springframework.jdbc.support.AbstractFallbackSQLExceptionTranslator.translate(AbstractFallbackSQLExceptionTranslator.java:80)
at org.springframework.jdbc.support.AbstractFallbackSQLExceptionTranslator.translate(AbstractFallbackSQLExceptionTranslator.java:80)
at org.springframework.jdbc.core.JdbcTemplate.execute(JdbcTemplate.java:602)
at org.springframework.jdbc.core.JdbcTemplate.query(JdbcTemplate.java:636)
at org.springframework.jdbc.core.JdbcTemplate.query(JdbcTemplate.java:665)
at org.springframework.jdbc.core.JdbcTemplate.query(JdbcTemplate.java:673)
at org.springframework.jdbc.core.JdbcTemplate.queryForObject(JdbcTemplate.java:728)
at org.springframework.jdbc.core.JdbcTemplate.queryForObject(JdbcTemplate.java:744)
at org.springframework.jdbc.core.JdbcTemplate.queryForInt(JdbcTemplate.java:775)
... 45 more
Caused by: java.sql.SQLException: Invalid column type
at oracle.jdbc.driver.SQLStateMapping.newSQLException(SQLStateMapping.java:70)
at oracle.jdbc.driver.DatabaseError.newSQLException(DatabaseError.java:133)
at oracle.jdbc.driver.DatabaseError.throwSqlException(DatabaseError.java:199)
at oracle.jdbc.driver.DatabaseError.throwSqlException(DatabaseError.java:263)
at oracle.jdbc.driver.DatabaseError.throwSqlException(DatabaseError.java:271)
at oracle.jdbc.driver.DatabaseError.throwSqlException(DatabaseError.java:445)
at oracle.jdbc.driver.OraclePreparedStatement.setObjectCritical(OraclePreparedStatement.java:7937)
at oracle.jdbc.driver.OraclePreparedStatement.setObjectInternal(OraclePreparedStatement.java:7517)
at oracle.jdbc.driver.OraclePreparedStatement.setObjectInternal(OraclePreparedStatement.java:8174)
at oracle.jdbc.driver.OraclePreparedStatement.setObject(OraclePreparedStatement.java:8155)
at oracle.jdbc.driver.OraclePreparedStatementWrapper.setObject(OraclePreparedStatementWrapper.java:230)
at org.jboss.resource.adapter.jdbc.WrappedPreparedStatement.setObject(WrappedPreparedStatement.java:724)
at org.springframework.jdbc.core.StatementCreatorUtils.setValue(StatementCreatorUtils.java:351)
at org.springframework.jdbc.core.StatementCreatorUtils.setParameterValueInternal(StatementCreatorUtils.java:216)
at org.springframework.jdbc.core.StatementCreatorUtils.setParameterValue(StatementCreatorUtils.java:144)
at org.springframework.jdbc.core.ArgPreparedStatementSetter.doSetValue(ArgPreparedStatementSetter.java:65)
at org.springframework.jdbc.core.ArgPreparedStatementSetter.setValues(ArgPreparedStatementSetter.java:46)
at org.springframework.jdbc.core.JdbcTemplate$1.doInPreparedStatement(JdbcTemplate.java:641)
at org.springframework.jdbc.core.JdbcTemplate.execute(JdbcTemplate.java:586)
... 56 more
Based on the stacktrace it looks like you are using the JdbcTemplate class. Since you are using the named parameter style place holders and providing a MapSqlParameterSource for the parameters you need to use the NamedParameterJdbcTemplate.
So, why are you getting this strange error message? Well, your SQL query actually works using the Oracle JDBC driver. It does allow you to use either "?" or a named parameter style using a ":" as the prefix fro the placeholders. You still need to provide the parameter values in the correct order which the MapSqlParameterSource in your case does not. You can test this by using an Object array instead like:
new Object[] {custVo.getProdId(), DAOConstants.FLAG_Y}
The error is based on the values coming in the wrong order from the params.getValues() method, with the String value being passed in for the :PROD_ID.

Categories

Resources