I have an SQL query that is executed using Spring JDBCTemplate to retrieve data from an Oracle DB. While executing the statement, org.springframework.jdbc.BadSqlGrammarException is thrown.
The same SQL statement returns proper results when run in the SQL Plus console.
Below is the code that I am trying to execute:
String query = "SELECT DISTINCT O.ORGID FROM ORGANISATIONS O WHERE O.ORGTYPE NOT IN ('P','G') AND O.USERID = 40";
ArrayList<Organisations> orgsList = new ArrayList<Organisations>();
Object[] paramsArray = new Object[]{};
orgsList = (ArrayList<Organisations>) getJdbcTemplate().query(query.toString(), paramsArray ,
new RowMapper<Organisations>(){
public MetricsRoleMap mapRow(ResultSet rs, int rowNum) throws SQLException {
// Data retrieval code;
};
});
Here is the error generated:
org.springframework.jdbc.BadSqlGrammarException: PreparedStatementCallback; bad SQL grammar [ SELECT DISTINCT O.ORGID FROM ORGANISATIONS O WHERE O.ORGTYPE NOT IN ('P','G') AND O.USERID = 40]; nested exception is java.sql.SQLException: Invalid column name
at org.springframework.jdbc.support.SQLErrorCodeSQLExceptionTranslator.doTranslate(SQLErrorCodeSQLExceptionTranslator.java:231) [spring-jdbc-4.0.5.RELEASE.jar:4.0.5.RELEASE]
at org.springframework.jdbc.support.AbstractFallbackSQLExceptionTranslator.translate(AbstractFallbackSQLExceptionTranslator.java:73) [spring-jdbc-4.0.5.RELEASE.jar:4.0.5.RELEASE]
at org.springframework.jdbc.core.JdbcTemplate.execute(JdbcTemplate.java:660) [spring-jdbc-4.0.5.RELEASE.jar:4.0.5.RELEASE]
at org.springframework.jdbc.core.JdbcTemplate.query(JdbcTemplate.java:695) [spring-jdbc-4.0.5.RELEASE.jar:4.0.5.RELEASE]
at org.springframework.jdbc.core.JdbcTemplate.query(JdbcTemplate.java:727) [spring-jdbc-4.0.5.RELEASE.jar:4.0.5.RELEASE]
at org.springframework.jdbc.core.JdbcTemplate.query(JdbcTemplate.java:737) [spring-jdbc-4.0.5.RELEASE.jar:4.0.5.RELEASE]
at org.springframework.jdbc.core.JdbcTemplate.query(JdbcTemplate.java:787) [spring-jdbc-4.0.5.RELEASE.jar:4.0.5.RELEASE]
Similar code that I wrote for another method works well. I think there is a minor mistake here, but I am unable to find it.
Related
I am using JDBCTemplate to query a SQL server using:
List results = jdbc.query(statement, new ResultDataMapper());
I have tried the statement in PreparedStatementCreator and String formats but neither work. I received the exception below:
SQL state [null]; error code [0]; The statement did not return a result set.; nested exception is com.microsoft.sqlserver.jdbc.SQLServerException: The statement did not return a result set.
My sql is:
IF OBJECT_ID('tempdb.dbo.#tempSearch', 'U') IS NOT NULL
DROP TABLE #tempSearch;
CREATE TABLE #tempSearch
(
ID int,
Value VARCHAR(255)
)
INSERT INTO #tempSearch
VALUES(1,'?'),
(2,'?');
with cte as (
select RoleID,','+replace(replace(GroupNames,',',',,'),' ','')+',' GroupNames from UserGroup_Role_Mapping
)
,cte2 as(
select cte.RoleID, replace(cte.GroupNames,','+Value+',','') as GroupNames, s.ID, s.Value
from cte
join #tempSearch s on ID=1
union all
select cte2.RoleID, replace(cte2.GroupNames,','+s.Value+',','') as l, s.ID ,s.Value
from cte2
join #tempSearch s on s.ID=cte2.ID+1
)
SELECT a.Role, a.Sort_Order, a.Parent, a.Parent_ID, a.Parent_URL, a.Child, a.Child_ID,a.Child_URL
FROM NC_View a
WHERE a.Role IN (
Select Name from (
Select distinct RoleID from cte2 where len(GroupNames)=0
) tempRoles
join User_Role
on tempRoles.RoleID = User_Role.ID
)
DROP TABLE #tempSearch
I know the SQL works fine but i just cant get over the hump of calling it from JDBC. I have the Mapper and extractor all done too.
I ran this with a PreparedStatementCreator and String:
when i use PreparedstatementCreator and try to set 2 variables I get index out range errors "com.microsoft.sqlserver.jdbc.SQLServerException: The index 1 is out of range.":
PreparedStatementCreator returnValue = new PreparedStatementCreator() {
#Override
public PreparedStatement createPreparedStatement(Connection con) throws SQLException {
sql.append("("+x +",'" + "?" +"'),"); //when constructing the sql
PreparedStatement statement = con.prepareStatement(sql.toString());
statement.setString(z++, group); //when setting those values
I am not sure why this is? is the syntax incorrect? It seems it is not detecting the set?
from debug i also see:
Unable to translate SQLException with Error code '0'
If I use String straight out i get:
org.springframework.jdbc.UncategorizedSQLException: StatementCallback; uncategorized SQLException for SQL [
SQL FROM ABOVE - I TESTED AND IT WORKS
]; SQL state [null]; error code [0]; The statement did not return a result set.; nested exception is com.microsoft.sqlserver.jdbc.SQLServerException: The statement did not return a result set.
I am not sure if the SQL is too complex or what. But also confused how using PreparedStatementCreator it wasnt detecting the ? to set variables... I am running out of ideas. I tried Multiqueries=true too
If I use SET NOCOUNT ON i get a different error:
Unable to solve uncategorized SQLException when calling SQL Server using JDBC
So i am bit confused too. I am not inserting a lot of data so maybe it doesn't matter?
Thanks!
I am trying to fetch data from MySQL stored procedure in hibernate . I have a custom_query.xml file , and DAO.java file
stored procedure in MySQL :
CREATE DEFINER=`root`#`localhost` PROCEDURE `SET_NETWORK`(
IN TO_CREATE BIGINT,
OUT CREATED BIGINT
)
BEGIN
SET CREATED = (SELECT COUNT(VNR.ID) FROM NETWORK_TABLE VNR);
WHILE (CREATED < TO_CREATE) DO
INSERT INTO NETWORK_TABLE (ACTIVE) VALUES(0);
SET CREATED = CREATED + 1;
END WHILE;
END
and i am trying to execute the SQL query from hibernate with following code :
<sql-query name="Network_getFreeNetworksForDomain" read-only="false" callable="true" cacheable="false"><![CDATA[
{ ? = CALL SET_NETWORK(?,?) }
]]></sql-query>
and in DAO.java file , i am using Network_getFreeNetworksForDomain for calling the SQL query :
#Override
#Transactional(readOnly = true)
#SuppressWarnings({"unchecked"})
public List<Network> getNetworksForDomain(Domain domain) throws DataAccessException {
Long domainId = domain.getId();
if (domainId == null) {
domainId = 0L;
}
return (List<Network>) getSession().getNamedQuery("Network_getFreeNetworksForDomain")
.setLong("dId", domainId).list();
}
but i am getting following excretion while deploying the file in to JBoss
Caused by: java.sql.SQLException: Can't set IN parameter for return value of stored function call.
at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:1055) [mysql-connector-java-5.1.6.jar:]
at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:956) [mysql-connector-java-5.1.6.jar:]
at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:926) [mysql-connector-java-5.1.6.jar:]
at com.mysql.jdbc.PreparedStatement.checkBounds(PreparedStatement.java:3294) [mysql-connector-java-5.1.6.jar:]
at com.mysql.jdbc.PreparedStatement.setInternal(PreparedStatement.java:3272) [mysql-connector-java-5.1.6.jar:]
at com.mysql.jdbc.PreparedStatement.setInternal(PreparedStatement.java:3314) [mysql-connector-java-5.1.6.jar:]
at com.mysql.jdbc.PreparedStatement.setLong(PreparedStatement.java:3330) [mysql-connector-java-5.1.6.jar:]
at org.jboss.jca.adapters.jdbc.WrappedPreparedStatement.setLong(WrappedPreparedStatement.java:229)
at com.dao.entity.NetworkHibernateDAO$1.createCallableStatement(NetworkHibernateDAO.java:169) [dao-impl-6.4.0.jar:]
at com.dao.hibernate.transaction.HibernateUtils.execute(HibernateUtils.java:106) [dao-impl-6.4.0.jar:]
at com.dao.hibernate.transaction.HibernateUtils$1.doInConnection(HibernateUtils.java:74) [dao-impl-6.4.0.jar:]
at com.dao.hibernate.transaction.HibernateUtils$2.execute(HibernateUtils.java:91) [dao-impl-6.4.0.jar:]
at org.hibernate.impl.SessionImpl.doWork(SessionImpl.java:1987) [hibernate-core-3.5.6-Final.jar:3.5.6-Final]
... 51 more
and
Caused by: org.springframework.orm.hibernate3.HibernateJdbcException: JDBC exception on Hibernate data access: SQLException for SQL [???]; SQL state [S1009]; error code [0]; error executing work; nested exception is org.hibernate.exception.GenericJDBCException: error executing work
Any suggestion ? How to solve this kind of errors ?
Update :
In DB2 and PostgreSQL this is working fine with
<sql-query name="Network_getFreeNetworksForDomain" read-only="false" callable="true" cacheable="false"><![CDATA[
{ ? = CALL SET_NETWORK(?) }
]]></sql-query>
but getting same exception mentioned above . so i have added CALL SET_NETWORK(?,?) with two parameter with mys stored procedure .
{ ? = CALL SET_NETWORK(?,?) }
It' seems you need 2 parameters and you provided only one
.setLong("dId", domainId)
I'm not sure your code is able to find the "dId" parameter, maybe you should use the index instead, you can have some sample in the official documentation
I wrote the following method in repository
#Query(value = "delete from bin_values where id in (select bv.id from bin_values bv inner join bin b on bv.bin_id = b.id where b.stat_id = ?1)", nativeQuery = true)
void deleteByStatId(long statId);
unfortunately, when I run this function, the following error occurs:
Exception in thread "main"
org.springframework.orm.jpa.JpaSystemException: could not extract
ResultSet; nested exception is
org.hibernate.exception.GenericJDBCException: could not extract
ResultSet
Caused by: org.hibernate.exception.GenericJDBCException: could not
extract ResultSet
Caused by: java.sql.SQLException: Query does not return results
Of course it has no results, since it is delete query. How to force it go?
This query runs fine from SQL Developer : select * from MYTABLE where (field1, field2) IN (('A', '1'), ('B','2'), ('C','3')) ;
But when I try to call it from java I am getting exception.
public List<MYVO> callDB(List<String> sourceAndIdList) {
System.out.println(sourceAndIdList);
String query = "select * from MYTABLE where (field1, field2) IN (:source_monitorId_list)";
Map<String, List<String>> namedParameters = Collections.singletonMap("source_monitorId_list", sourceAndIdList);
return this.namedParameterJdbcTemplate.query(query , namedParameters, new RowMapper<MYVO>() {
#Override
public MYVO mapRow(ResultSet rs, int rowNum) throws SQLException {
....
}
});
}
One printing my list I am getting : [('A', '1'), ('B', '2'), ('C', '3')]
Exception:
SEVERE: Servlet.service() for servlet [selfservice] in context with
path [/mymonitoring] threw exception [Request processing failed;
nested exception is org.springframework.jdbc.BadSqlGrammarException:
PreparedStatementCallback; bad SQL grammar [select * from MYTABLE
where (field1, field2) IN (?, ?, ?)]; nested exception is
java.sql.SQLSyntaxErrorException: ORA-00920: invalid relational
operator ] with root cause java.sql.SQLSyntaxErrorException:
ORA-00920: invalid relational operator
EDIT: This is not a duplicate as I am looking for a solution with springs NamedParameterJdbcTemplate for a query having multiple IN clause and the size of parameters are known only at runtime.
You can't use bind parameter like this in an "IN".
Either you do :
IN ((:p1, :p2), (:p3,:p4), (:p5,:p6))
But it assumes you know exactly how many items you have (in this case 3) or you "materialize" your parameters in the SQL string:
String query = "select * from MYTABLE where (field1, field2) IN (('A', '1'), ('B', '2'), ('C', '3'))";
I'm trying to use nested queries with JdbcTemplate but found the issue, it seems to me that it's doesn't suppot nested queries.. Am i right? or what i need to change?
So, i invoke
getJdbcTemplate().query(request, new Object[]{name}...)
// request is query which you can see in error message
which gives results in oracle but failes with
org.springframework.jdbc.InvalidResultSetAccessException: PreparedStatementCallback; invalid ResultSet access for SQL [select sq.name as name from (select t1.name as name from table1 t1 left outer join table2 t2 on t2.id = t1.fk_id where t1.name is not null ) sq where upper(name) like upper('?')]; nested exception is java.sql.SQLException: Invalid column index
EDITED
request is a simple String object which is actually an sql that you see in exception message. The eturn object has no matter in this situation as i left it empty (for testing ourpose)
but just for you to be sure here it is:
List<MyObject> list = getJdbcTemplate().query(request, new Object[]{"Somename"}, new RowMapper() {
public Object mapRow(ResultSet rs, int rowNum) throws SQLException {
return new MyObject();
}
});
Try changing the upper('?') to upper(?). By putting the ? in quotes, the database doesn't realize that you're dealing with a parameter.