JDBC Exception when setting parameters on a prepared statement - java

I would appreciate the help with the following:
I am getting JDBCException when setting parameters onto JDBC prepared statement.
The fragment of the query where the error is looks like this
... AND (tbl1.field1, tbl2.field2) IN ((?, ?), (?, ?)) ...
And my list of parameters is a an ArrayList of values
{123, 235689, 25,2568982}
If I run the query in the SQLDeveloper, substituting values for '?' - I get the right result
But, when running in the Java program it throws the JDBCException
An JDBC exception occurred. Statement: SELECT ... FROM .. WHERE ..AND (tbl1.field1,
tbl2.field2) IN ((?, ?), (?, ?)) .. Invalid column index
The debugger brings me to the line that does this:
statement.setLong(i, lp.longValue());
where 'statement' is a PreparedStatement ..

Your current WHERE IN tuple syntax is not valid for Oracle:
AND (tbl1.field1, tbl2.field2) IN ((?, ?), (?, ?))
This only would work on MySQL and a few other databases. You should refactor it to:
WHERE (tbl1.field1 = ? AND tbl2.field2 = ?) OR (tbl1.field1 = ? AND tbl2.field2 = ?)
Then, iterate your list of values and assign the 4 ? placeholders appropriately. As the comment above notes, your exact error could be due to an array index problem, but even if you fix that, the syntax would still fail for Oracle.

Related

Passing 'select from dual' as parameter to java callable statement

I am trying to pass SELECT FROM DUAL as parameter to callable statement in java as in example:
{?=call function1( ?, (select function2(?) from dual), ?)}
When I call this function I get exception: ORA-06550: line 1, column 165: PLS-00103: Encountered the symbol "SELECT" when expecting one of the following: ( - + case mod new not null others...
When I call function as {?=call function1( ?, ?, ?)}, it works fine, but I need to call another function as a parameter (password encryption for example).
Is there a way to call one function as parameter to another function?
How about
BEGIN function1( ?,function2(?), ?) END;
or
{?=call function1( ?, function2(?), ?)}
You don't need to call dual. Just in case, you can always use PL/SQL itself. Easy to to use and maintain.
Oracle Docs
Returning data from anonymous PL/SQL block - contains some useful code snippets on PL/SQL usage in JDBC.

How to solve bad sql grammar error with Spring JDBC?

I'm using PostgreSQL with Spring JDBC. Everythig building with Gradle:
dependencies {
compile("org.springframework.boot:spring-boot-starter-web")
compile("org.springframework:spring-jdbc")
compile("postgresql:postgresql:9.0-801.jdbc4")
compile("com.h2database:h2")
compile("com.googlecode.json-simple:json-simple:1.1")
testCompile("junit:junit")
}
Here is code fragment where I got exception:
String sql = "INSERT INTO " + dbname + " (:fields) VALUES (:values)";
MapSqlParameterSource parameters = new MapSqlParameterSource();
parameters.addValue( "fields", fieldsObj.keySet().toArray() );
parameters.addValue( "values", fieldsObj.values().toArray() );
count = jdbcTemplate.update( sql, parameters );
I get this error:
PreparedStatementCallback; bad SQL grammar [INSERT INTO test (?, ?, ?) VALUES (?, ?, ?)]; nested exception is org.postgresql.util.PSQLException
I've tried to convert array into string with values, divided by commas, but this gave me same error. What should I do? Or, if you have better ideas what to use, to build custom queries, please, post this idea in comments.
You can't use value placeholders ("?") for things that aren't values (like your field-names).
If you really want to do this, just build up the query, mapping the field-names in. Then apply the values with placeholders.
BUT do make sure you check the field-names are as you would expect and escape/quote them properly.
Oh - Not a java programmer, but do check that keySet() and values() return their results in the same order too.
Edit:
The "?" marks are value placeholders. They are used in database connection libraries of all sorts. They will be mapped to whatever parameterised query syntax the database can use. However, they only work for values - so the database can parse the query with the placeholders.

Mysql insert query not working on insert

i am getting JDBC 3.0 getParameterType call not supported exception, when trying to insert query into mysql. getting below exception
2013-10-26 20:04:25 [http-apr-8080-exec-9] DEBUG [org.springframework.jdbc.core.StatementCreatorUtils] - - JDBC 3.0 getParameterType call not supported
java.sql.SQLException: Parameter metadata not available for the given statement
at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:1078)
at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:989)
at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:975)
at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:920)
at com.mysql.jdbc.MysqlParameterMetadata.checkAvailable(MysqlParameterMetadata.java:70)
at com.mysql.jdbc.MysqlParameterMetadata.getParameterType(MysqlParameterMetadata.java:119)
at org.springframework.jdbc.core.StatementCreatorUtils.setNull(StatementCreatorUtils.java:231)
at org.springframework.jdbc.core.StatementCreatorUtils.setParameterValueInternal(StatementCreatorUtils.java:213)
at org.springframework.jdbc.core.StatementCreatorUtils.setParameterValue(StatementCreatorUtils.java:144)
at org.springframework.jdbc.core.ArgumentPreparedStatementSetter.doSetValue(ArgumentPreparedStatementSetter.java:65)
at org.springframework.jdbc.core.ArgumentPreparedStatementSetter.setValues(ArgumentPreparedStatementSetter.java:46)
at org.springframework.jdbc.core.JdbcTemplate$2.doInPreparedStatement(JdbcTemplate.java:822)
at org.springframework.jdbc.core.JdbcTemplate$2.doInPreparedStatement(JdbcTemplate.java:818)
at org.springframework.jdbc.core.JdbcTemplate.execute(JdbcTemplate.java:589)
at org.springframework.jdbc.core.JdbcTemplate.update(JdbcTemplate.java:818)
at org.springframework.jdbc.core.JdbcTemplate.update(JdbcTemplate.java:874)
at org.springframework.jdbc.core.JdbcTemplate.update(JdbcTemplate.java:882)
i am using spring 3.2.4 tomcat 7 and mysql connector 5.1.26. It appears strange for me , because i have other daos which does insert and select.
when i run junit test case, i could successfully insert the data.
help needed. thanks.
EDIT- code causing the error
jdbcTemplate.update(
ADD_DATA,
new Object[] { IdKey, model.getType(), model.getUserId(), model.getDate(),
model.getPlace(), model.getArea(); ,model.getAddressBO().getCity(), model.getAddressBO().getState() });
sql query
INSERT INTO model (model_ID, model_TYPE_ID, USER_ID, model_DATE, model_PLACE, model_AREA, CITY_ID, STATE_ID) VALUES (?, ?, ? ,?, ?, ?, ? ,?) ";
the exception is misleading to debug, i fixed it, since date field is mandatory and dont accept null. i was inserting null. it worked upon giving data

using combined update and insert with hypersql

I was implementing upsert according to this great post: Insert, on duplicate update in PostgreSQL? and this works really fine with psql. However, I can't fire the same query into hsqldb which i use for testing.
my sql looks like this:
UPDATE account set name = ?, email = ?, type = ?, regts = ?, dao_updated = ? WHERE id = ?;
INSERT INTO account (id, name, email, type, regts, dao_created,dao_updated) SELECT ?,?,?,?,?,?,? WHERE NOT EXISTS (SELECT 1 FROM account WHERE id = ? );
I get the error message:
Caused by: java.sql.SQLSyntaxErrorException: unexpected token: INSERT
at org.hsqldb.jdbc.Util.sqlException(Unknown Source)
at org.hsqldb.jdbc.Util.sqlException(Unknown Source)
at org.hsqldb.jdbc.JDBCPreparedStatement.<init>(Unknown Source)
at org.hsqldb.jdbc.JDBCConnection.prepareStatement(Unknown Source)
Is this a limitation of hsqldb or am I doing something wrong?
thanks in advance
Leon
HSQLDB supports the MERGE statement for this:
http://hsqldb.org/doc/2.0/guide/dataaccess-chapt.html#dac_merge_statement
The merge statement is generally more powerful than UPSERT and non-standard alternatives.
Alternatively, you can use CREATE PROCEDURE and define a procedure similar to the PostgreSQL example given in the linked answer.
http://hsqldb.org/doc/2.0/guide/sqlroutines-chapt.html#src_psm_conditional
You can use the GET DIAGNOSTICS statement to find out if the update succeeded.
http://hsqldb.org/doc/2.0/guide/dataaccess-chapt.html#dac_diagnostics_state
You apparently can't use several statements inside single executeUpdate() call. Please, call twice first time doing UPDATE, next time doing INSERT

Getting hibernate to log clob parameters

(see here for the problem I'm trying to solve)
How do you get hibernate to log clob values it's going to insert. It is logging other value types, such as Integer etc.
I have the following in my log4j config:
log4j.logger.net.sf.hibernate.SQL=DEBUG
log4j.logger.org.hibernate.SQL=DEBUG
log4j.logger.net.sf.hibernate.type=DEBUG
log4j.logger.org.hibernate.type=DEBUG
Which produces output such as:
(org.hibernate.SQL) insert into NoteSubstitutions (note, listIndex, substitution) values (?, ?, ?)
(org.hibernate.type.LongType) binding '170650' to parameter: 1
(org.hibernate.type.IntegerType) binding '0' to parameter: 2
(org.hibernate.SQL) insert into NoteSubstitutions (note, listIndex, substitution) values (?, ?, ?)
(org.hibernate.type.LongType) binding '170650' to parameter: 1
(org.hibernate.type.IntegerType) binding '1' to parameter: 2
However you'll note that it never displays parameter: 3 which is our clob.
What I would really want is something like:
(org.hibernate.SQL) insert into NoteSubstitutions (note, listIndex, substitution) values (?, ?, ?)
(org.hibernate.type.LongType) binding '170650' to parameter: 1
(org.hibernate.type.IntegerType) binding '0' to parameter: 2
(org.hibernate.type.ClobType) binding 'something' to parameter: 3
(org.hibernate.SQL) insert into NoteSubstitutions (note, listIndex, substitution) values (?, ?, ?)
(org.hibernate.type.LongType) binding '170650' to parameter: 1
(org.hibernate.type.IntegerType) binding '1' to parameter: 2
(org.hibernate.type.ClobType) binding 'something else' to parameter: 3
How do I get it to show this in the log?
Try using:
log4j.logger.net.sf.hibernate=DEBUG
log4j.logger.org.hibernate=DEBUG
That's the finest level you'll get. If it does not show the information you want, then it's not possible.
Well, it looks like you can't. (Thanks Marcio for the suggestion, but sadly that didn't add anything useful)
Try to set log4j.logger.org.hibernate.type=TRACE and see if that helps.

Categories