Below is a generic class I wrote that calls a stored procedure on the server:
public class StoredProc {
Connection con = null;
ResultSet rs = null;
CallableStatement cs = null;
public StoredProc(String jdbcResource, String storedProcName){
this(jdbcResource, storedProcName, new String[0], new String[0]);
}
public StoredProc(String jdbcResource, String storedProcName, String[] params,String[] paramTypes){
Connection con = new databaseConnection(jdbcResource).getConnection();
//Get length of parameters and sets stored procs params (?, ?, ...etc)
String procParams = "";
int paramSize = params.length;
if(paramSize != 0){
for(int i = 0; i < paramSize; i++){
if(i == paramSize){
procParams += "?";
}else{
procParams += "?, ";
}
}
}
try{
CallableStatement cs = this.con.prepareCall("{?=call "+storedProcName+" ("+procParams+")}");
for(int j = 0; j < params.length; j++){
if (paramTypes[j].equalsIgnoreCase("Int")) {
int x = 0;
try{
x = Integer.parseInt(params[j]);
} catch(Exception e) {}
cs.setInt(j, x);
} else if (paramTypes[j].equalsIgnoreCase("Boolean")) {
boolean x = false;
try{
x = (params[j].equalsIgnoreCase("True")) || (params[j].equalsIgnoreCase("T")) || (params[j].equalsIgnoreCase("1")) || (params[j].equalsIgnoreCase("Yes")) || (params[j].equalsIgnoreCase("Y"));
} catch(Exception e) {}
cs.setBoolean(j, x);
} else if (paramTypes[j].equalsIgnoreCase("String")) {
cs.setString(j, params[j]);
}
}
}catch(Exception e){
System.out.println("---------------------------------------------");
System.out.println("Problem constructing callableStatement: "+e);
System.out.println("---------------------------------------------");
}
}
public ResultSet runQuery(){
try{
rs = cs.executeQuery();
}catch(SQLException e){
System.out.println("---------------------------------------------");
System.out.println("Problem executing stored procedure: "+e);
System.out.println("---------------------------------------------");
}
return rs;
}
public void runUpdate(){
try{
cs.executeUpdate();
}catch(SQLException e){
System.out.println("---------------------------------------------");
System.out.println("Problem executing stored procedure: "+e);
System.out.println("---------------------------------------------");
}
}
} //end of class
for some reason I'm getting a NullPointerException on the line I'm trying to construct a CallableStatement --> CallableStatement cs = this.con.prepareCall("{?=call "+storedProcName+" ("+procParams+")}");
The callable statement should look like this at run time:
cs = this.con.prepareCall({?=call getUnlinkedDirectdeposits()});
The stored proc is called this in the database: [dbo].[getUnlinkedDirectdeposits]
Any help would be appreciated!
Thanks in advance,
You are using the wrong "con" variable. In your method you're initialising a variable (local to the method) called con:
Connection con = new databaseConnection(jdbcResource).getConnection();
But then you use this.con, which is the con field of the StoredProc object you're currently executing in. Since it was never initialised, you get a NullPointerException.
Your Connection field is null!
You create a new Connection instance in StoredProc instead of assigning it to the field con of your class. But when trying to created the CallableStatement your are using the this.con which has not been set before.
Related
In Java, how do I pass values of type set to a procedure. This seems too basic, but I can't solve it, I spent days searching sample Java code on how to pass set values to Informix procedure.
Tools
IBM Informix Dynamic Server Version 12.10.FC13
JDBC 4.10.14, 4.50.7
Java version "1.8.0_172"
Informix procedure
create procedure sp_demo_set_arg(
arg1 set(integer not null)
)
...
end procedure
Java code
#Override
public Integer callProcedure(List<Integer> listOfId) {
String sql = "{ call sp_demo_set_arg(?) }";
#SuppressWarnings("rawtypes")
java.util.HashSet arg1 = new HashSet();
Integer intObject;
int i;
for (i=1; i <= 3; i++)
{
intObject = new Integer(i);
arg1.add(intObject);
}
Connection conn = null;
try {
conn = dataSource.getConnection();
CallableStatement stmt = conn.prepareCall(sql);
stmt.setObject(1, arg1);
stmt.executeUpdate();
return 0;
} catch (SQLException e) {
e.printStackTrace();
}
return 1;
}
Stacktrace
...
java.sql.SQLException: Routine (sp_demo_set_arg) can not be resolved.
at com.informix.jdbc.IfxSqli.addException(IfxSqli.java:3133)
at com.informix.jdbc.IfxSqli.receiveError(IfxSqli.java:3417)
at com.informix.jdbc.IfxSqli.dispatchMsg(IfxSqli.java:2324)
at com.informix.jdbc.IfxSqli.receiveMessage(IfxSqli.java:2249)
at com.informix.jdbc.IfxSqli.executeCommand(IfxSqli.java:850)
at com.informix.jdbc.IfxResultSet.executeUpdate(IfxResultSet.java:230)
at com.informix.jdbc.IfxStatement.executeUpdateImpl(IfxStatement.java:1054)
at com.informix.jdbc.IfxPreparedStatement.executeUpdate(IfxPreparedStatement.java:396)
at
...
Your java code may fail with an -674 "Routine can not be resolved" error because the server may not know the parameter type at execution.
Try giving it some 'hints' changing '?' for a '?::SET(integer not null)'
Something like:
D:\Infx\work\Java>cat t2.java
import java.sql.*;
import java.util.*;
public class t2 {
public static void main( String [] args ) {
Connection conn = null;
ResultSet dbRes = null;
Statement is = null;
try {
Class.forName("com.informix.jdbc.IfxDriver");
conn = DriverManager.getConnection("jdbc:informix-sqli://420ito:9091/stores7:INFORMIXSERVER=ids1410;user=informix;password=passw;SQLIDEBUG=pp;");
is = conn.createStatement();
is.executeUpdate("drop table t2; create table t2 (c1 SET(integer not null) );");
java.util.HashSet arg1 = new HashSet();
Integer intObject;
int i;
for (i=1; i <= 3; i++)
{
intObject = new Integer(i);
arg1.add(intObject);
}
try {
//CallableStatement stmt = conn.prepareCall("{ CALL p2(?)}");
CallableStatement stmt = conn.prepareCall("{ CALL p2(?::SET(integer not null))}");
stmt.setObject(1, arg1);
stmt.executeUpdate();
} catch (SQLException e) {
e.printStackTrace();
}
Statement st = conn.createStatement();
ResultSet rs = st.executeQuery("SELECT * FROM t2");
while (rs.next()) {
java.util.HashSet set = (HashSet) rs.getObject(1);
Iterator it = set.iterator();
Object obj;
i = 0;
while (it.hasNext())
{
obj = it.next();
System.out.println(" element[" + i + "] = " + obj.toString());
i++;
}
}
rs.close();
conn.close();
}
catch ( Exception e ) {
System.err.println(e);
e.printStackTrace();
}
}
}
D:\Infx\work\Java>javac t2.java
Note: t2.java uses unchecked or unsafe operations.
Note: Recompile with -Xlint:unchecked for details.
D:\Infx\work\Java>java t2
element[0] = 1
element[1] = 2
element[2] = 3
D:\Infx\work\Java>
I have created an API module of spring boot application to call stored procedure. When it comes to the implementation, stmt.execute cannot be called with no response. Would you please tell me which module or wayout to modify under my java environment is 1.8?
int retVal = -1;
int errCode = -1;
String errText = null;
int outPos;
int pos = 0;
System.out.println("call 2");
String SQL_SELECT = "{call database_sid.test_pkg.get_pc_lue(?,?,?,?,?,?)}";
try (Connection conn = DriverManager.getConnection(DBC_URL, USERNAME, PASSWORD);
CallableStatement preparedStatement = conn.prepareCall(SQL_SELECT);
) {
System.out.println("call db");
preparedStatement.setString(++pos, "OFFER_TYPE");
preparedStatement.setString(++pos, null); // acct srv limit
preparedStatement.registerOutParameter(outPos = ++pos, Types.REF_CURSOR);
preparedStatement.registerOutParameter(++pos, Types.INTEGER);
preparedStatement.registerOutParameter(++pos, Types.INTEGER);
preparedStatement.registerOutParameter(++pos, Types.VARCHAR);
System.out.println("call 10");
ResultSet resultSet = preparedStatement.executeQuery();
System.out.println("call 11");
while (resultSet.next()) {
String value = resultSet.getString("LOOKUP_VALUE");
String type = resultSet.getString("LOOKUP_TYPE");
PcTblBPcLookUp obj = new PcTblBPcLookUp();
obj.setLookUpValue(value);
obj.setLookUpType(type);
result.add(obj);
System.out.println("call 1obecj1");
}
result.forEach(x -> System.out.println(x));
System.out.println("call finish ");
} catch (SQLException e) {
System.err.format("SQL State: %s\n%s", e.getSQLState(), e.getMessage());
} catch (Exception e) {
e.printStackTrace();
System.out.println("call error : " + e.getMessage());
}
You need to execute your stored procedure using execute and then you need to fetch your resultset from opsition registered for out parameter
preparedStatement.execute();
ResultSet rs = (ResultSet) preparedStatement.getObject(outPos);
I have code, where I have single quote or APOSTROPHE in my search
I have database which is having test table and in name column of value is "my'test"
When running
SELECT * from test WHERE name = 'my''test';
this works fine
If I use the same in a Java program I am not getting any error or any result
But If I give the name with only single quote then it works
SELECT * from test WHERE name = 'my'test';
Could you please help me out to understand.
Java code is
Connection con = null;
PreparedStatement prSt = null;
try {
Class.forName("oracle.jdbc.driver.OracleDriver");
con = DriverManager.
getConnection("jdbc:oracle:thin:#localhost:1521:orcl"
,"user","pwd");
String query = "SELECT * from "
+ "WHERE name = ? ";
prSt = con.prepareStatement(query);
String value = "my'mobile";
char content[] = new char[value.length()];
value.getChars(0, value.length(), content, 0);
StringBuffer result = new StringBuffer(content.length + 50);
for (int i = 0; i < content.length; i++) {
if (content[i] == '\'')
{
result.append("\'");
result.append("\'");
}
else
{
result.append(content[i]);
}
}
prSt.setObject(1, result.toString());
int count = prSt.executeUpdate();
System.out.println("===============> "+count);
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
} finally{
try{
if(prSt != null) prSt.close();
if(con != null) con.close();
} catch(Exception ex){}
}
You don't have to escape anything for the parameter of a PreparedStatement
Just use:
prSt = con.prepareStatement(query);
prSt.setString("my'mobile");
Additionally: if you are using a SELECT statement to retrieve data, you need to use executeQuery() not executeUpdate()
ResultSet rs = prst.executeQuery();
while (rs.next())
{
// process the result here
}
You might want to go through the JDBC tutorial before you continue with your project: http://docs.oracle.com/javase/tutorial/jdbc/index.html
gurus,
I am new to Java SQL, and need some help.
I'm trying to get a parameter from MS SQL Server 2008. The data is definitely there - it is a current and valid DB, and I'm trying to use the users records to get cridentials for another application.
I asserted the following query:
String query = "SELECT [USER].qc_number FROM [USER] WHERE "[USER].login_name = '"
+ userNameInput + "' AND [USER].password = '" + passWordInput + "';";
Where userNameInput and passWordInput are received from the user. The URL, query and driver class are definitely correct: I checked the DB schema both from the application and from the server views. Furthermore, I verified all the Exceptions systems by changing parameters one by one, resulting in correct Exceptions messages. However, I get a resultSet with 1 column and 0 rows.
The code is below:
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
public class trOdbc
{// database URL
final String DB_URL = "***";
final String Class_URL = "com.microsoft.sqlserver.jdbc.SQLServerDriver";
private Connection connection = null; // manages connection
private Statement statement = null; // query statement
private ResultSet resultSet = null; // manages results
private Boolean connectedToDatabase = false;
// ----------------------------------------------------------
public void createJdbcConnection()
{ // connect to database books and query database
if (connectedToDatabase)
{ return; }
try
{ // connectedToDatabase is false - establish the connection
Class.forName(Class_URL);
connection = DriverManager.getConnection
(DB_URL, "***", "***" );
statement = connection.createStatement
(ResultSet.TYPE_SCROLL_INSENSITIVE,
ResultSet.CONCUR_READ_ONLY);
connectedToDatabase = true;
}
catch (SQLException ex)
{ System.out.println ("SQL Exception in connection establishment: " + ex); }
catch (ClassNotFoundException ex)
{ System.out.println ("Class not found exception in query process: " + ex); }
}
// ----------------------------------------------------------
public String [][] processJdbcQuery (String query)
{
createJdbcConnection ();
if (!connectedToDatabase)
{ return null; }// the connection wasn't established
try
{// query database
resultSet = statement.executeQuery(query);
int columns = resultSet.getMetaData().getColumnCount();
int rows = 0;
if (resultSet != null)
{
resultSet.beforeFirst();
resultSet.last();
rows = resultSet.getRow();
}
String [][] tempData = new String[rows][columns];
resultSet.beforeFirst();
rows = 0;
while (resultSet.next())
{
for (int x = 1; x <= columns; x++)
{
tempData [rows][x - 1] = resultSet.getString (x);
}
rows++;
}
CloseJdbcConnection ();
return tempData;
}
catch (SQLException ex)
{
System.out.println ("SQL Exception in query process: " + ex);
CloseJdbcConnection ();
return null;
}
} // end processJdbcQuery
// ----------------------------------------------------------
public void CloseJdbcConnection()
{
if ( connectedToDatabase )
{// close Statement and Connection. resultSet is closed automatically.
try
{
statement.close();
connection.close();
connectedToDatabase = false;
}
catch (SQLException ex)
{ System.out.println ("SQL Exception in connection closure: " + ex); }
} // end if
} // end method CloseJdbcConnection
} // end class trOdbc
Why don't you use Prepared Statement instead ?
Here is a good tutorial for using prepared statement in java
In your case it would be :
String query = "SELECT [USER].qc_number FROM [USER] " +
"WHERE [USER].login_name = ? AND [USER].password = ?;";
And then set it with different values each time you execute it like :
PreparedStatement ps = connection.prepareStatement(query);
ps.setString(1, userNameInput);
ps.setString(2, passWordInput);
resultSet = ps.executeQuery();
I'm having a strange problem with the below code, it works fine when its run without the if else statements, but displays no results in the jtable when if else is used. Is there something stupid I'm missing here?
try {
Class.forName(dbClass);
Connection con = DriverManager.getConnection (dbUrl,dbUsername, dbPassword);
Statement stmt = con.createStatement();
String userQuery = "SELECT p_id AS 'Patient ID', forename AS 'Forename', surname AS 'Surname', address AS 'Address' FROM Patient WHERE surname LIKE '%"+s+"%'";
ResultSet userResult = stmt.executeQuery(userQuery);
if(!userResult.next())
{
JOptionPane.showMessageDialog(null, "No Results.");
{
else{
ResultSetMetaData rsMetaData =userResult.getMetaData();
DefaultTableModel dtm = new DefaultTableModel();
int cols = rsMetaData.getColumnCount();
Vector colName = new Vector();
Vector dataRows = new Vector();
for (int i=1; i<cols; i++){
colName.addElement(rsMetaData.getColumnName(i));
}
dtm.setColumnIdentifiers(colName);
while(userResult.next()){
dataRows = new Vector();
for(int j = 1; j<cols; j++){
dataRows.addElement(userResult.getString(j));
}
dtm.addRow(dataRows);
}
searchTable.setModel(dtm);
con.close();
}
} //end try
catch(ClassNotFoundException e) {
JOptionPane.showMessageDialog(null, "Database Error.");
e.printStackTrace();
}
catch(SQLException e) {
JOptionPane.showMessageDialog(null, "Database Error.");
e.printStackTrace();
}
I'm using netbeans for the GUI.
Thanks
The connection object (con) should be closed outside if/else block.
Beside, the userResult.next() was called twice in the else statement block..
You may fix it by replacing while() by do while loop:
do {
dataRows = new Vector();
for (int j = 1; j < cols; j++) {
dataRows.addElement(userResult.getString(j));
}
dtm.addRow(dataRows);
}
while (userResult.next());
Please include finally to handle closing the connection and removing the other resources.