SPRING jdbcTemplate.update java.sql.SQLException: No value specified for parameter - spring

I'have already solved the problem but i just wondered why jdbcTemplate not accept my query with the jdbcTemplate.update but work with jdbcTemplate.execute, here the code for the example with coordinates:
String query = "UPDATE geodomaindocument SET latitude=? , longitude=? WHERE url=?";
Object[] values = new Object[]{0,0,"http://example.com"}
jdbcTemplate.update(query, values);
return this exception:
org.springframework.jdbc.BadSqlGrammarException: PreparedStatementCallback; bad SQL grammar [UPDATE geodomaindocument SET latitude=? , longitude=? WHERE url=?]; nested exception is java.sql.SQLException: No value specified for parameter 2
but is worked with the same query but with the execute:
query = "UPDATE geodomaindocument SET latitude='"+values[0]+"', longitude='"+values[1]+"' WHERE url='http://example.com'";
jdbcTemplate.execute(query);
Ty in advance for any help.
UPDATE
Ok,I'm just stupid, it's was a simple index error.

Your latitude and longitude are of type string. Try this
Object[] values = new Object[]{"0","0","http://example.com"}

Related

HANA query with dynamic placeholder executed using jdbcTemplate in Spring Boot

I have a few HANA queries that rely on PLACEHOLDER input. The input to this is currently hardcoded which is leading to SQL injection vulnerability being detected by Veracode.
In order to fix that, I am trying to parameterize the value given to PLACEHOLDER using PreparedStatement, but getting the below error :
PreparedStatementCallback; uncategorized SQLException for SQL [SELECT * FROM some_table (PLACEHOLDER.\"$$<IP_SOME_COLUMN>$$\" => ?) WHERE some_flag = ?; ]; SQL state [HY000]; error code [2048]; SAP DBTech JDBC: [2048]: column store error: search table error: [34023] Instantiation of calculation model failed;exception 306002: An internal error occurred\n; nested exception is com.sap.db.jdbc.exceptions.JDBCDriverException: SAP DBTech JDBC: [2048]: column store error: search table error: [34023] Instantiation of calculation model failed;exception 306002: An internal error occurred
I have already checked this solution and gone through the documentation for input parameters in SAP HANA. Below is my code :
String sqlQuery = SELECT * FROM some_table ( PLACEHOLDER.\"$$<IP_SOME_COLUMN>$$\" => ? ) WHERE some_flag = ? ;
PreparedStatementSetter preparedStatementSetter = (PreparedStatement ps) -> {
ps.setString(1, firstInput);
ps.setString(2, secondInput);
}
ResultSetExtractor<T> rse = new DataResultSetExtractor();
getJdbcTemplate().query(sqlQuery, preparedStatementSetter, rse);
The same works well with the hardcoded way (prone to SQL injection) :
StringBuffer sql = new StringBuffer();
sql.append("SELECT * FROM some_table ").append("( 'PLACEHOLDER' = ('$$IP_SOME_COLUMN$$',").append(firstColumnValue).append("))");
//Map<String,Object> paramMap = new HashMap<String,Object>();
//getNamedParameterJdbcTemplate().query(sql.toString(), paramMap, rse);
How do I fix this error?
Figured the issue out. It seems, in the new syntax you need to provide the input parameter in single quotes and not in triple single quotes
Works : 'foo'
Doesn't work : '''bar'''

How to use oracle NVL function in spring data repository nativeQuery

I am trying to use oracle' NVL function in nativeQuery of Spring Data Repository.
While i am passing null value in programId parameter then it is throwing exception (ORA-00932: inconsistent datatypes: expected NUMBER got BINARY) and if i am passing a valid value in "programId" then it is working properly.
public interface ProgramRulesRepository
{
public static final String FIND_PROGRAM_RULES_BY_PARTICIPANT_ID_AND_ROLE_OR_PROGRAM = " SELECT DISTINCT pr.id , pr.program_id , prgm.display_name , pr.group_id , pr.type , pr.cmmo_key FROM program prgm , program_rule pr , program_audience pa , participant_audience paa WHERE prgm.id = pa.program_id AND pr.program_id = pa.program_id AND pa.audience_id = paa.audience_id AND pr.type = :roleType AND paa.participant_id = :participantId "
+ " AND pr.program_id = NVL ( :programId ,pr.program_id )";
#Query( value = FIND_PROGRAM_RULES_BY_PARTICIPANT_ID_AND_ROLE_OR_PROGRAM, nativeQuery = true )
List<Object[]> findByParticipantIdAndRoleTypeOrProgramId( #Param( "participantId" ) Long participantId, #Param( "roleType" ) String roleType, #Param( "programId" ) Long programId );
}
Exception :
Caused by: java.sql.SQLSyntaxErrorException: ORA-00932: inconsistent datatypes: expected NUMBER got BINARY
Avoid NVL and COALESCE when using Hibernate. COALESCE function needs to have all parameters of the same type. NVL is using implicit casting which doesn't work well when there is BINARY or VARBINARY. And where this BINARY came from? Well, Hibernate is setting NULL value as type of BINARY and ignores the real datatype backed by Java. When you set logging level to trace you can see in output:
binding parameter [1] as [VARBINARY] - [null]
So when the other type of in COALESCE or NVL function is for example NUMBER, you will get that error ORA-00932.
A good solution for this problem is this:
" AND (:programId IS NULL OR pr.program_id = :programId)"
Doing this way, if your param is null this sentence will result TRUE and won't discard the register, and if it is not null will be compared with the value stored in its field.
I have faced this problem with MongoDB. But I could solve this problem by using mongoTemplate as like,
Query query = new Query();
Criteria criteria = new Criteria();
List<Criteria> orCriterias = new ArrayList<>();
if( dto.getId() != null) {
orCriterias.add(Criteria.where("id").is(Integer.parseInt(dto.getId())));
}
... so on for other fields
criteria.orOperator(orCriterias.toArray(new Criteria[orCriterias.size()]));
query.addCriteria(criteria);
List<StudentDTO> recordsList = mongoTemplate.find(query, StudentDTO.class,
"student_collection");

Exception weblogic.deployment.QueryProxyImpl cannot be cast to javax.persistence.TypedQuery when I build a Criteria-Based TypedQuery

Good day!
I'm using a Criteria Query to build a query to a table, with some predicates, like this:
CriteriaBuilder cb = em.getCriteriaBuilder();
CriteriaQuery q = cb.createQuery();
Root<Foo> root = q.from(Foo.class);
List<Predicate> predicates = new ArrayList<Predicate>();
[added some predicates]
q.select(root).where(predicates.toArray(new Predicate[]{}));
As you can see, there is nothing strange in this code snippet...but when I build the typed query to get the result list of the query:
TypedQuery<Foo> finalQuery = em.createQuery(q);
List<Foo> result = finalQuery.getResultList();
I get an exception when I run in Weblogic 10.3.5, in the typed query creation line:
weblogic.deployment.QueryProxyImpl cannot be cast to javax.persistence.TypedQuery
I build this entire code snippet based on a Oracle Example, which you can find in this URL: http://docs.oracle.com/javaee/6/tutorial/doc/gjrij.html
What do you think could be the error?
Thanks to everyone!
EDIT: This exception is showed when you haven't put the JPA 2 library in the weblogic classpath. You have to add the next line in your commEnv.sh/commEnv.cmd file:
Linux:
PRE_CLASSPATH=${BEA_HOME}/modules/javax.persistence_1.0.0.0_2-0-0.jar:${BEA_HOME}/
modules/com.oracle.jpa2support_1.0.0.0_2-0.jar
export PRE_CLASSPATH
Windows:
set PRE_CLASSPATH=%BEA_HOME%\modules\javax.persistence_1.0.0.0_2-0-
0.jar;%BEA_HOME%\modules\com.oracle.jpa2support_1.0.0.0_2-0.jar
try writing:
CriteriaQuery<Foo> q = cb.createQuery();
before you had:
CriteriaQuery q = cb.createQuery();
I had similar problem but while creating a namedquery instead of createQuery. Previously it was working fine. But when TransactionAttribute, TransactionAttributeType.Not_SUPPORTED, it is throwing weblogic.deployment.QueryImpl cannot be cast to TypedQuery. When I removed the transaction attribute, it worked!

Can any one tell me what is wrong with PrepareStatement syntax

public ResultSet readSubSet(int No, String name, String case) throws SQLException {
preparedStatement = connect.prepareStatement("SELECT * FROM target WHERE myName=? AND myCase=? LIMIT ?,10");
preparedStatement.setString(8, name);
preparedStatement.setString(6, case);
preparedStatement.setInt(1, No);
resultSet = preparedStatement.executeQuery();
return resultSet;
}
After run I got: java.sql.SQLException: Parameter index out of range (8 > number of parameters, which is 2).
my table define myName and myCase is TEXT, is that ok I use prepareStatement.setString
When you call setString you pass in two arguments, the first is the index of the parameter you are filling in and the second is the value you are filling it with. In your case, you would want prepareStatement.setString(1,name); to fill in the 1st parameter, prepareStatement.setString(2,case); to fill in the 2nd parameter, and so on.
In your SQL you only have 3 variables and you are setting variable 8 as name in preparedStatement.setString(8, name)...
Look # http://download.oracle.com/javase/tutorial/jdbc/basics/prepared.html#supply_values_ps

calling derby (java db) 'show tables' from jdbc

I need to enumerate the tables in a Derby (aka Java DB) database using JDBC in a Java program. All I am aware of for doing this is the SHOW TABLES command.
I first tried with something similar to this...
String strConnectionURL = "jdbc:derby:/path/to/derby/database;create=false";
Class.forName("org.apache.derby.jdbc.EmbeddedDriver");
Connection connection = DriverManager.getConnection(strConnectionURL);
Statement statement = connection.createStatement();
boolean boResult = statement.execute("SHOW TABLES");
if (boResult) {
System.out.println("yay!");
}
...but that throws an exception:
java.sql.SQLSyntaxErrorException: Syntax error: Encountered "SHOW" at line 1, column 1.
So next I thought maybe I needed to use a CallableStatement so I tried this...
String strConnectionURL = "jdbc:derby:/path/to/derby/db;create=false";
Class.forName("org.apache.derby.jdbc.EmbeddedDriver");
Connection connection = DriverManager.getConnection(strConnectionURL);
CallableStatement statement = connection.prepareCall("SHOW TABLES");
boolean boResult = statement.execute();
if (boResult) {
System.out.println("yippee!");
}
...but that throws the same exception:
java.sql.SQLSyntaxErrorException: Syntax error: Encountered "SHOW" at line 1, column 1.
So, can anyone help me enumerate the tables in my Derby (Java DB) database from JDBC?
EDIT: I'm looking around and starting to get a feeling this may be a general JDBC question. In other words, one could/would enumerate all a db's tables with the DatabaseMetaData object that can be retrieved from the Connection object. Looking into that (and looking forward to responses)...
EDIT 2: I found a pure JDBC solution, but am still happy to hear alternatives...
String strConnectionURL = "jdbc:derby:/path/to/db;create=false";
Class.forName("org.apache.derby.jdbc.EmbeddedDriver");
Connection connection = DriverManager.getConnection(strConnectionURL);
DatabaseMetaData dbmd = connection.getMetaData();
ResultSet resultSet = dbmd.getTables(null, null, null, null);
while (resultSet.next()) {
String strTableName = resultSet.getString("TABLE_NAME");
System.out.println("TABLE_NAME is " + strTableName);
}
Show Tables is an ij command, not a base SQL statement, so you can't directly execute it. As you noted in your "EDIT 2", you can use the DatabaseMetaData to do this. Two other ways to do it are: you can select from the system catalogs (see http://db.apache.org/derby/docs/10.8/ref/rrefsistabs24269.html) , or you can use the "ij.runScript" method to run the ij tool from within your program, and pass it the "show tables" command (see http://db.apache.org/derby/docs/10.8/publishedapi/jdbc3/org/apache/derby/tools/ij.html)
As Bryan suggested ij.runScript - the code would look like this:
public void showTbls() throws Exception{
String sqlIn = "SHOW TABLES;";
InputStream stream = new ByteArrayInputStream(sqlIn.getBytes(StandardCharsets.UTF_8));
ij.runScript(conn,stream,StandardCharsets.UTF_8.name(), System.out,"UTF-8");
stream.close();
}
assumming conn is a opened derby Connection
But the disadvantage is that you are getting only string output. Not an ResultSet as you would get from:
Statement stmt = conn.createStatement();
ResultSet results = stmt.executeQuery("SELECT * FROM sys.systables");
or if you want only user table names you can use following SQL:
ResultSet results = stmt.executeQuery("SELECT TABLENAME FROM SYS.SYSTABLES WHERE TABLETYPE='T'");
A very similar output to
SHOW TABLES;
can be produced by using the following jdbc compliant query:
SELECT TABLENAME, (SELECT SCHEMANAME
FROM SYS.SYSSCHEMAS
WHERE SYS.SYSTABLES.SCHEMAID = SYS.SYSSCHEMAS.SCHEMAID)
AS SCHEMANAME
FROM SYS.SYSTABLES WHERE TABLETYPE='T'
It also shows you the probably useful SCHEMA information for each TABLE entry. Skip
TABLETYPE='T'
if you also want to see the system tables of your database as the user before has mentioned already.

Resources