Spring Transient Data Access Resource Exception in jdbcTemplate update - sql

I have a method to detect duplicate entry for a column:
(I inject to jdbcTemplate correctly)
private boolean isDuplicate(String username) {
String sql = " select username from users where username=?";
int result = jdbcTemplate.update(sql, new Object[]{username}, String.class);
return result;
}
But i got this exception in runtime:
org.springframework.dao.TransientDataAccessResourceException:
PreparedStatementCallback; SQL [ select username from users where username=?]; Invalid argument value: java.lang.ArrayIndexOutOfBoundsException;
nested exception is java.sql.SQLException: Invalid argument value: java.lang.ArrayIndexOutOfBoundsException

We can use the queryForList() method of jdbcTemplate like this:
results = jdbcTemplate.queryForList(sql,new Object[]{username},String.class);
if(results.isEmpty(){
//no duplicate
}
else{
//duplicate
}
Where results is a List<String>.

Related

How to correct bad sql grammar when passing data?

This is my JDBC file with a the following sql query:
private static final String UPDATE_QUESTION = "UPDATE Quiz SET type=?, questionIndex=?, choiceNum=?, question=?, choiceA=?, choiceB=?, choiceC=?, choiceD=?, correct=?, hint=? WHERE type=? AND questionIndex=?";
When I try and pass some data into the query above in JSON format:
{
"id": 84,
"type":"epidemics",
"questionIndex": 1,
"choiceNum":2,
"question":"updated question3",
"choiceA": "no3",
"choiceB":"yes2",
"choiceC":"no3",
"choiceD":"yes4",
"correct":"no3",
"hint":"second answer"
}
I am getting the following error message:
"timestamp": "2022-11-26T11:52:16.431+00:00",
"status": 500,
"error": "Internal Server Error",
"trace": "org.springframework.jdbc.BadSqlGrammarException: PreparedStatementCallback; bad SQL grammar [UPDATE Quiz SET type=?, questionIndex=?, choiceNum=?, question=?, choiceA=?, choiceB=?, choiceC=?, choiceD=?, correct=?, hint=? WHERE (type=?) AND (questionIndex=?)]; nested exception is java.sql.SQLException: No value specified for parameter 12
Any ideas where I'm going wrong in the query?
Note that you need to pass a value for each ? placeholder, even if the same column appears more than once in the prepared statement. So, you need to bind the value for questionIndex twice. Your Java code should look something like:
String UPDATE_QUESTION = "UPDATE Quiz SET type=?, questionIndex=?, choiceNum=?, question=?, choiceA=?, choiceB=?, choiceC=?, choiceD=?, correct=?, hint=? WHERE type=? AND questionIndex=?";
PreparedStatement ps = conn.prepareStatement(UPDATE_QUESTION);
ps.setString(1, type);
ps.setInt(2, questionIndex); // first setter for questionIndex
ps.setInt(3, choiceNum);
ps.setString(4, question);
ps.setString(5, choiceA);
ps.setString(6, choiceB);
ps.setString(7, choiceC);
ps.setString(8, choiceD);
ps.setString(9, correct);
ps.setString(10, hint);
ps.setString(11, type);
ps.setInt(12, questionIndex); // second setter for questionIndex
int row = ps.executeUpdate();
// rows affected
System.out.println(row);

is it possible to get the execute sql that contains parameter when debugging mybatis source

I am setting a breakpoint in mybatis source BaseExecutor's queryFromDatabase function in Intellij Idea, this code block look like this:
private <E> List<E> queryFromDatabase(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, CacheKey key, BoundSql boundSql) throws SQLException {
List<E> list;
localCache.putObject(key, EXECUTION_PLACEHOLDER);
try {
list = doQuery(ms, parameter, rowBounds, resultHandler, boundSql);
} finally {
localCache.removeObject(key);
}
localCache.putObject(key, list);
if (ms.getStatementType() == StatementType.CALLABLE) {
localOutputParameterCache.putObject(key, parameter);
}
return list;
}
but the boundSql content shows sql like this:
select * from article where channel_id in (?)
is it possible to get the execute sql in the trace? because the channel_id has more than 100 and the sql also contains other filter condition.

jdbcTemplate.query works fine when passing few parameters and doesn't work for others

I have a select Oracle SQL that I am hitting using jdbcTemplate.query method. This returns a bean of the values from the table. I am passing a dynamic value to the query that will be used in the WHERE clause. However, the SQL values for few values that i am passing. But when I pass the value as NA it won't work. Any suggestions on this or help me with what am i missing?
private static final String regionSearchSql = "SELECT PRFLID, PRFLNM, RGN_CD FROM %PREFIX%MER_PRFL WHERE RGN_CD = ?";
public List<SearchProfileBean> regionSearchProfile(SearchProfileRequest searchProfileRequest) throws DatabaseQueryException {
try {
return jdbcTemplate.query((QueryUtility.getQueryWithPrefix(regionSearchSql,prefix)), new SearchProfileRowMapper(), searchProfileRequest.getRegionName());
} catch (Exception e) {
throw new DatabaseQueryException(QueryUtility.getQueryWithPrefix(regionSearchSql, prefix), e);
}
}
If i pass 'EMEA', 'LAC', 'JAPA' in searchProfileRequest.getRegionName() - the SQL returns perfect results. But if I pass 'NA' in searchProfileRequest.getRegionName(), it gives empty results. But there are rows in the table for NA.

Apache DBUtils - Why need resultsethandler for Insert?

I run an insert statement using Apache DBUtils. However, I am not sure why I have to include ResultSetHandler for this case:
String theQuery = QueryGenerator.insertintoStats();
ResultSetHandler<Object> dummyHandler = new ResultSetHandler<Object>() {
#Override
public Object handle(ResultSet rs) throws SQLException
{
return null;
}
};
try
{
queryRunner.insert(connection, theQuery, dummyHandler, Constants.UUIDSTR.toString(), name, prevbackupTime,
curbackupTime, updStartTime, delStartTime, bkupType.toString(), rowCount);
}
catch (SQLException e)
{
LOGGER.info(theQuery.toString());
LOGGER.error("Caught exception!", e);
}
Similar's the case for insertbatch which does use ResultSetHandler. I have resorted to use batch call for batch queries. Can anyone explain why we would be needing resultset handler for insert?
From documentation https://commons.apache.org/proper/commons-dbutils/apidocs/:
public <T> T insert(String sql,
ResultSetHandler<T> rsh,
Object... params)
throws SQLException
rsh - The handler used to create the result object from the ResultSet
of auto-generated keys.
If you insert values in a table which generate id upon insertion, you can retrieve it back, for example see this answer how to do this manually : https://stackoverflow.com/a/1915197/947111
You need ResultSetHandler<T> rsh to iterate over ResultSet which returned with id's which has been created.

HQL :Hibernate update query

i use struts2 and hibernate jpa for my app and i have an error when traying using update query with hibernate
here is my code :
in my class dao
#Override
public void UpdateNoteEvaluation() {
try {
String hql="update Evaluation e " +
"SET e.Eval_NoteGlobal =: ( SELECT SUM( sv.SousEval_Note ) AS sum FROM sousevaluation sv )" +
"ORDER BY EVAL_ID DESC LIMIT 1 ";
Query q= session.createQuery(hql);
q.executeUpdate();
} catch (Exception e) {
transaction.rollback();
e.printStackTrace();
}
}
in my class Action :
public String saveOrUpdate(){
sousevaldao.UpdateNoteEvaluation();
System.out.println("update note ok ok");
return SUCCESS;
}
so here i can't make the update i get this error :
java.lang.IllegalArgumentException: node to traverse cannot be null!
at org.hibernate.hql.ast.util.NodeTraverser.traverseDepthFirst(NodeTraverser.java:55)
at org.hibernate.hql.ast.QueryTranslatorImpl.parse(QueryTranslatorImpl.java:277)
knowing i have test the update query im phpmyadmin it's work fine
If query has been tested to be working one via phpMyAdmin, it is quite clear that query is SQL query - not a HQL query. Also syntax of query seems to contain MySQL SQL dialect specific LIMIT clause.
Query for native SQL queries can be created via Session.createSQLQuery(String queryString) method:
String sql = ...
Query q = session.createSQLQuery(sql);