Execute a stored procedure in connected Oracle Database on Java - java

I have a stored procedure in Oracle Database like this:
CREATE OR REPLACE PROCEDURE PSTATISTIC
AS
BEGIN
UPDATE PLACE_STATISTIC
SET POPULARITY = 0;
UPDATE PLACE_STATISTIC
SET POPULARITY = POPULARITY + 1
WHERE PLACE_ID IN (SELECT PLACE_COMMENT.PLACE_ID
FROM PLACE_COMMENT);
END PSTATISTIC;
When I called it on SQL Developer:
EXECUTE PSTATISTIC
It executed normally, the PLACE_STATISTIC table was updated
But when I tried to use it on Java:
String sql="EXECUTE HR.PSTATISTIC";
Statement statement=(Statement)connectionDB.createStatement();
statement.execute(sql);
It didn't work out on Java, citing sort of errors:
java.sql.SQLSyntaxErrorException: ORA-00900: invalid SQL statement
at oracle.jdbc.driver.T4CTTIoer.processError(T4CTTIoer.java:439)
at oracle.jdbc.driver.T4CTTIoer.processError(T4CTTIoer.java:395)
at oracle.jdbc.driver.T4C8Oall.processError(T4C8Oall.java:802)
at oracle.jdbc.driver.T4CTTIfun.receive(T4CTTIfun.java:436)
at oracle.jdbc.driver.T4CTTIfun.doRPC(T4CTTIfun.java:186)
at oracle.jdbc.driver.T4C8Oall.doOALL(T4C8Oall.java:521)
at oracle.jdbc.driver.T4CStatement.doOall8(T4CStatement.java:194)
at oracle.jdbc.driver.T4CStatement.executeForRows(T4CStatement.java:1000)
at oracle.jdbc.driver.OracleStatement.doExecuteWithTimeout(OracleStatement.java:1307)
at oracle.jdbc.driver.OracleStatement.executeInternal(OracleStatement.java:1882)
at oracle.jdbc.driver.OracleStatement.execute(OracleStatement.java:1847)
at oracle.jdbc.driver.OracleStatementWrapper.execute(OracleStatementWrapper.java:301)
How can I execute my PSTATISTIC procedure on Java? I granted all necessary privileges

To execute a stored procedure from Java code, you need to use CallableStatement. Statement cant be used to execute Stored Proc.
Connection con = getConnection();
CallableStatement cs = null;
try {
cs = con.prepareCall("{call EXECUTE PSTATISTIC}");
cs.execute();
} catch (SQLException e) {
System.err.println("SQLException: " + e.getMessage());
}
finally {
if (cs != null) {
try {
cs.close();
} catch (SQLException e) {
System.err.println("SQLException: " + e.getMessage());
}
}
if (con != null) {
try {
con.close();
} catch (SQLException e) {
System.err.println("SQLException: " + e.getMessage());
}
}
}
}

You need to use CallableStatement for executing your Stored procedure
String procName= "{call PSTATISTIC}";
CallableStatement cs = conn.prepareCall(procName);
cs.executeQuery();

Related

Issue Running MySQL Stored Procedure from Java

I have a bizarre issue where I can execute a stored procedure from the command line, and directly on the mysql instance, however, when I run the stored procedure from Java, I am getting an error:
Cannot delete or update a parent row: a foreign key constraint fails
My code is:
public void runCleanCustomerDataStoredProcedures() {
ResultSet rs = Db.getInstance().runQuery("SELECT DATABASE();");
String database = null;
try {
while (rs.next()) {
database = rs.getString("DATABASE()");
}
} catch (SQLException e) {
logger.error(e.getMessage());
}
ArrayList<String> batchIDs = Db.getInstance().getDistinctFieldsFromTable("id","batch");
Db.getInstance();
for (String batchID : batchIDs){
String query = "{ call " + database + ".delete_batch_and_data(?,?,?,?)}";
ExecuteStoredProcedure(query, batchID);
}
ArrayList<String> custIDs = Db.getInstance().getDistinctFieldsFromTable("id","customer");
Db.getInstance();
for (String custID : custIDs){
String query = "{ call " + database + ".delete_customer_and_data(?,?,?,?)}";
ExecuteStoredProcedure(query,custID);
}
Db.destroyInstance();
}
public void ExecuteStoredProcedure(String query, String id){
CallableStatement callableStatement = null;
try {
callableStatement = con.prepareCall(query);
callableStatement.setString(1,id);
callableStatement.setString(2,"");
callableStatement.setString(3,"");
callableStatement.setString(4,"");
callableStatement.registerOutParameter(4, Types.VARCHAR);
callableStatement.execute();
DbOps.getInstance().runQuery("commit;");
callableStatement.close();
} catch (SQLException e) {
logger.error("Problem occurred while executing callable statement: " + callableStatement, e);
}
}
Any ideas or advice would be greatly appreciated. I find it extremely weird that I can execute manually via client and command line with no issues :(

Java - execute stored procedure

I need to execute procedure from sql using java.
I have call my procedure in sql management like exec MyProcedure and works well.
But when I use it in java code I get error :
The statement did not return a result set.
This is my code:
ResultSet rs = null;
PreparedStatement cs = null;
Connection conn = DbM.dbConnect();
try {
cs = conn.prepareStatement("exec MyProcedure ?,?,?");
cs.setEscapeProcessing(true);
cs.setQueryTimeout(90);
cs.setString(1, "1");
cs.setString(2, "2019-01-01");
cs.setString(3, "2019-02-02");
rs = cs.executeQuery();
ArrayList<Data> listaObjectX = new ArrayList<Data>();
while (rs.next()) {
Data to = new Data();
to.setEmployeNo(rs.getString(1));
to.setValidFrom(rs.getDate(2));
to.setValidTo(rs.getDate(3));
listaObjectX.add(to);
}
} catch (SQLException se) {
System.out.println("Error al ejecutar SQL"+ se.getMessage());
se.printStackTrace();
throw new IllegalArgumentException("Error al ejecutar SQL: " + se.getMessage());
} finally {
try {
rs.close();
cs.close();
conn.close();;
} catch (SQLException ex) {
ex.printStackTrace();
}
}
When run code I got error:
The statement did not return a result set.
Any idea how to solve this problem?
If I put cs= conn.prepareStatement("exec MyProcedure (?,?,?)");
I get error
Incorrect syntax near '#P0'
If this procedure is not returning a result, you should be using execute() instead of executeQuery() which is expected to always return a ResultSet.

Reading ResultSet: java.sql.SQLException: Operation not allowed after ResultSet closed

I'm trying to get information from a MySQL database. I can connect and do things such as insert data into tables fine, and although I receive a ResultSet, I can't read it. Here's my code:
public ResultSet executeQuery(String query) {
Statement stmt = null;
ResultSet rs = null;
try {
stmt = conn.createStatement();
rs = stmt.executeQuery(query);
if (stmt.execute(query)) {
rs = stmt.getResultSet();
}
return rs;
}
catch (SQLException ex){
System.err.println("SQLException: " + ex.getMessage());
System.err.println("SQLState: " + ex.getSQLState());
System.err.println("VendorError: " + ex.getErrorCode());
}
finally {
if (stmt != null) {
try {
stmt.close();
} catch (SQLException sqlEx) { } // ignore
stmt = null;
}
}
return null;
}
Trying to read the ResultSet:
ResultSet set = executeQuery("SELECT rank FROM players");
try {
while(set.next()) {
System.out.println(set.getInt("rank") + "");
}
} catch(Exception ex) {
ex.printStackTrace();
} finally {
try {
set.close();
} catch (SQLException e1) {
e1.printStackTrace();
}
}
I get this error:
java.sql.SQLException: Operation not allowed after ResultSet closed
I've been looking around the internet and on different forums all day. What's wrong with my code?
Your finally block in executeQuery closes your statement before you've iterated over the results.
Well, two things -
1) I do not get why you have both execute() and executeQuery() in your method? I think executeQuery() should work for you.
2) Do not close the statement before iterating through resultset. Make it an instance variable and close it after iterating.
TL;DR Your executeQuery closes the Statement.
From the JavaDoc for Statement.close
Releases this Statement object's database and JDBC resources
immediately instead of waiting for this to happen when it is
automatically closed.
You close() your Statement before you read your ResultSet. Closing a Statement causes all of the ResultSet instances associate with that Statement to also be closed.
You need to pass in a Consumer<ResultSet> into a different method, and process the ResultSet whilst the Statement is open:
public void executeQuery(final String query, final Consumer<ResultSet> consumer) {
try(final Statement stmt = conn.createStatement();
final ResultSet rs = stmt.executeQuery(query)) {
consumer.accept(rs);
}
catch (SQLException ex){
System.err.println("SQLException: " + ex.getMessage());
System.err.println("SQLState: " + ex.getSQLState());
System.err.println("VendorError: " + ex.getErrorCode());
}
}
I have also fixed your code:
I have replaced your try..finally with a try-with-resources
You execute your query twice by calling stmt.executeQuery(query) and then stmt.execute(query). This is not only wasteful, but you lose the reference to the first ResultSet and if Statement.close didn't close all the associated resultsets you would have had a memory leak.

JDBC update using prepared statement

I am trying to update a table using Java JDBC. The method I am using does not throw any errors but the table is not updating. The create table method is below:
public static void Table()
{
Connection c = null;
Statement stmt = null;
try {
Class.forName("org.sqlite.JDBC");
c = DriverManager.getConnection("jdbc:sqlite:WalkerTechCars.db");
System.out.println("Opened database successfully");
stmt = c.createStatement();
String sql = "CREATE TABLE IF NOT EXISTS CUSTOMERS2 " +
"(PHONE TEXT PRIMARY KEY NOT NULL," +
" SURNAME TEXT NOT NULL, " +
" FIRSTNAME TEXT NOT NULL, " +
" HOME TEXT, " +
" ADDRESS TEXT, " +
" POSTCODE Text)";
stmt.executeUpdate(sql);
stmt.close();
c.close();
} catch ( Exception e ) {
System.err.println( e.getClass().getName() + ": " + e.getMessage() );
System.exit(0);
}
System.out.println("Customers2 created successfully");
}
The update method is below:
public static void updateCustomers()
{
Connection c = null;
PreparedStatement pstmt = null;
try {
Class.forName("org.sqlite.JDBC");
c = DriverManager.getConnection("jdbc:sqlite:WalkerTechCars.db");
c.setAutoCommit(false);
System.out.println("Opened database successfully");
String query = "UPDATE CUSTOMERS2 set ADDRESS = ? where PHONE = ? ";
pstmt = c.prepareStatement(query); // create a statement
pstmt.setString(1, "1"); // set input parameter 1
pstmt.setString(2, "DOES THIS WORK"); // set input parameter 2
pstmt.executeUpdate(); // execute update statement
pstmt.close();
c.close();
} catch ( Exception e ) {
System.err.println( e.getClass().getName() + ": " + e.getMessage() );
System.exit(0);
}
System.out.println("Update Completed successfully HELLO");
}
I have tried to find some clear instructions on this but cant find any. I do not really understand JDBC and prepared statement very well
When autoCommit is false (c.setAutoCommit(false);), you must manually commit the transaction...
Add...
c.commit()
After pstmt.executeUpdate();
You code also has a flaw, in that if some kind of error occurs during the preparation or execution of the statement, both the Connection and PreparedStatement could be left open, causing a resource leak
If you're using Java 7+ you can use the try-with-resources feature, for example...
try {
Class.forName("org.sqlite.JDBC");
try (Connection c = DriverManager.getConnection("jdbc:sqlite:WalkerTechCars.db")) {
c.setAutoCommit(false);
System.out.println("Opened database successfully");
String query = "UPDATE CUSTOMERS2 set ADDRESS = ? where PHONE = ? ";
try (PreparedStatement pstmt = c.prepareStatement(query)) {
pstmt.setString(1, "1"); // set input parameter 1
pstmt.setString(2, "DOES THIS WORK"); // set input parameter 2
pstmt.executeUpdate(); // execute update statement
c.commit();
}
} catch (SQLException exp) {
exp.printStackTrace();
}
} catch (ClassNotFoundException exp) {
exp.printStackTrace();
System.out.println("Failed to load driver");
}
This will ensure that regardless of how you leave the try block the resource will be closed.
You might also consider taking a look at the JDBC(TM) Database Access
Your update method will set ADDRESS to 1 if there is any row in table with PHONE = does this work.
Try to put Address in 1st Input parameter and Phone 2nd Input parameter
When a connection is created, it is in auto-commit mode.
We need to use [setAutoCommit] method only when we need to make Auto Commit false and make it manual commit after executing the query.
More details at Oracle site on JDBC Transaction.

How to call Stored Procedure and prepared statement

In the below code I want to call one stored procedures and execute one Query. I am facing error at statement.executeUpdate(); Please help in fixing it. I am not sure where it going wrong.
public void Dbexe() {
Connection connection;
connection = DatabaseConnection.getCon();
CallableStatement stmt;
try {
stmt = connection.prepareCall("{CALL optg.Ld_SOpp}");
stmt.executeUpdate();
stmt.close();
} catch (SQLException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
System.out.println("Stored Procedure executed");
//PreparedStatement statement = null;
// ResultSet rs = null;
try{
PreparedStatement statement;
try {
statement = connection.prepareStatement("MERGE INTO OPTG.R_VAL AS TARGET USING" +
........... +
"");
statement.executeUpdate(); //Here the exception is thrown
statement.close();
connection.commit();
connection.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
// statement = connection.prepareStatement(query);
//statement.close();
}
finally{
System.out.println("Data is copied to the Table");
}
}
Little off-topic: You should use CallableStatement instead if you want to call a store procedure (see documentation):
CallableStatement callableStatement = connection.prepareCall("{call opptymgmt.Load_SiebelOpportunity}");
ResultSet rs = callableStatement.executeQuery();
I would also suggest you check this topic How to properly clean up JDBC resources in Java?. It was very helpful to me.
Update: based on this stack trace:
com.ibm.db2.jcc.am.mo: DB2 SQL Error: SQLCODE=-104, SQLSTATE=42601, SQLERRMC=MERGE INTO OPPTYMGMT.REVENUE_VALIDAT;BEGIN-OF-STATEMENT;<variable_set>, DRIVER=4.7.85
The problem seems to be in the sql sentence you're trying to execute. I mean, is an error from DB2, not java. You should check your sql statement.
I got it working in this method:
PreparedStatement myStmt = conn.prepareStatement(sqlQuery);
myStmt.setInt(1, id); //position of parameter (1,2,3....) , value
ResultSet rs = myStmt.executeQuery();
while (rs.next()) {
int jobId = rs.getInt("jobId"); ....... }

Categories

Resources