problems running PLSQL using JDBC - java

I am trying to run a PLSQL script which I have as a string value with the following method.
I first create the procedure
then I create a callStatement to call it
and finally I add some parameters
I get the error message:
ORA-06575: Package or function PROCEDURE_NAME is in an invalid state
Any ideas what I can do about that?
This is the code:
public IResult createAndExecuteCallable(String queryText, String procedureName, Object[] parameter) {
IResult result = new Result();
String procedure = "create procedure "+procedureName+"("+queryText+")";
Connection connection = this.getDatabaseConnection().getConnection();
try {
connection.setAutoCommit(true);
Statement stmt = connection.createStatement();
stmt.executeUpdate(procedure);
CallableStatement statement = connection.prepareCall("call "+procedureName+"()");
commonPreparedStatment(statement,parameter);
try {
statement.executeUpdate();
} catch(SQLException se){
result = new Result(se);
} finally {statement.close();}
} catch(Exception e){
result = new Result(e);
} finally {
closeConnection(connection);
}
return result;
}

Thanks to the comments and some other help I found the solution. Here is the new middle part of the code, now including compilation:
connection.setAutoCommit(true);
PreparedStatement createStatement = connection.prepareStatement(queryCreateText);
PreparedStatement compileStatement = connection.prepareStatement(queryCompileText);
CallableStatement statement = connection.prepareCall(queryCallText);
commonPreparedStatment(statement, parameter);
try {
createStatement.executeUpdate();
log.info("create ok");
} catch (SQLException ignored) {
log.info(ignored.getMessage());
} finally {
log.info(queryCompileText);
createStatement.close();
}
try {
compileStatement.executeUpdate();
log.info("compile ok");
} catch (SQLException ignoredToo) {
log.info(ignoredToo.getMessage());
} finally {
compileStatement.close();
}
try {
statement.executeUpdate();
log.info("execute ok");
} catch (SQLException se) {
result = new Result(se);
} finally {
statement.close();
}
One additional obstacle was the file content of the plsql code. It contained line breaks and Oracle did not accept them. So I had to remove them before creating the procedure in Oracle:
queryCreateText = queryCreateText.replace("\r\n", " ");

Related

SQL query in Java does not work, no error is appearing but the data isn't appearung in DB

I try to insert a row to the database, but it doesn't appear in the table after running:
This is the main class:
public class Tester {
public static void main(String[] args) {
CouponsDbDao coupDbDao = new CouponsDbDao();
Coupon coupon = new Coupon(1, 0, Category.Food, null, null, null, null, 25, 0, null);
coupDbDao.addCoupon(coupon);
}
}
And this is the method:
public class CouponsDbDao {
public void addCoupon(Coupon coupon) {
try {
Connection connection = JdbcUtils.getConnection();
String sqlStatement = "insert into coupons (COMPANY_ID,CATEGORY_ID,TITLE,DESCRIPTION,START_DATE,END_DATE,AMOUNT,PRICE,IMAGE) values(?,?,?,?,?,?,?,?,?)";
PreparedStatement statement = connection.prepareStatement(sqlStatement);
statement.setInt(1, coupon.getCompanyId());
statement.setObject(2, coupon.getCategory());
statement.setString(3, coupon.getTitle());
statement.setString(4, coupon.getDescription());
statement.setDate(5, coupon.getStartDate());
statement.setDate(6, coupon.getEndDate());
statement.setInt(7, coupon.getAmount());
statement.setDouble(8, coupon.getPrice());
statement.setString(9, coupon.getImage());
} catch (Exception e) {
e.printStackTrace();
}
}
You need to execute the statement after setting values. Additionally, you need to close the connection created, the preparedstatement etc in a finally block.
public class CouponsDbDao {
Connection connection = null;
PreparedStatement statement = null;
public void addCoupon(Coupon coupon) {
try {
connection= JdbcUtils.getConnection();
String sqlStatement = "insert into coupons (COMPANY_ID,CATEGORY_ID,TITLE,DESCRIPTION,START_DATE,END_DATE,AMOUNT,PRICE,IMAGE) values(?,?,?,?,?,?,?,?,?)";
statement = connection.prepareStatement(sqlStatement);
statement.setInt(1, coupon.getCompanyId());
statement.setObject(2, coupon.getCategory());
statement.setString(3, coupon.getTitle());
statement.setString(4, coupon.getDescription());
statement.setDate(5, coupon.getStartDate());
statement.setDate(6, coupon.getEndDate());
statement.setInt(7, coupon.getAmount());
statement.setDouble(8, coupon.getPrice());
statement.setString(9, coupon.getImage());
statement.executeUpdate();
} catch (Exception e) {
e.printStackTrace();
}
finally{
if (statement != null) {
try {
statement.close();
} catch (SQLException e) { /* print here */}
}
if (connection != null) {
try {
connection.close();
} catch (SQLException e) { /* print here */}
}
}
}
As told by others you need to call executeUpdate to really perform the query:
Executes the SQL statement in this PreparedStatement object, which must be an SQL Data Manipulation Language (DML) statement, such as INSERT, UPDATE or DELETE
I suggest you also to use the try with resources:
The try-with-resources statement is a try statement that declares one or more resources. A resource is an object that must be closed after the program is finished with it. The try-with-resources statement ensures that each resource is closed at the end of the statement. Any object that implements java.lang.AutoCloseable, which includes all objects which implement java.io.Closeable, can be used as a resource.
This has been introduced in java 7 and let you eliminate the finally boiler plate code as follow:
// ORIGINAL CODE
Connection connection = ...
try {
connection = JdbcUtils.getConnection();
...
statement.executeUpdate();
} catch (Exception e) {
e.printStackTrace();
} finally {
if (statement != null) {
try {
statement.close();
} catch (SQLException e) { /* print here */}
}
if (connection != null) {
try {
connection.close();
} catch (SQLException e) { /* print here */}
}
}
becomes:
// USING try with resources
try (Connection connection = JdbcUtils.getConnection()) {
...
statement.executeUpdate();
} catch (Exception e) {
e.printStackTrace();
} // NO need of the finally block because connection is AutoCloseable
You need to execute update for statement, like:
statement.executeUpdate();

Operation not allowed after ResultSet closed during while loop

I'm having a problem with Resultset during while loop. It's giving me an error java.sql.SQLException: Operation not allowed after ResultSet closed and I can't figure this out. Can anyone help me out? Thanks!
public static void CandidatesPartyList_JComboBox() {
try {
conn1 = VotingSystem.con();
ps = conn1.prepareStatement("SELECT * FROM partylist WHERE p_status = 'Active' ORDER BY p_name ASC");
rs = ps.executeQuery();
candidates_filter_partylist.removeAllItems();
candidates_filter_partylist.addItem("- Select PartyList -");
while (rs.next()) { **<< The problem is coming from here**
candidates_filter_partylist.addItem(rs.getString("p_name"));
}
} catch (Exception e) {
e.printStackTrace();
} finally {
if (rs != null) {
try {
rs.close();
} catch (Exception e) {
e.printStackTrace();
}
}
if (ps != null) {
try {
ps.close();
} catch (Exception e) {
e.printStackTrace();
}
}
if (conn1 != null) {
try {
conn1.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
You've got static variables named conn1, ps, and rs. Static means there is only one variable for the entire virtual machine.
Clearly then, CandidatesPartyList_JComboBox is called twice by different threads and thus the variables are overwritten.
The solution is: None of those things should be fields. They should be local variables, and you should be using try-with-resources, which makes this code less than half the size and fixes the problem. Let's also fix the bad error handling ('print the stack trace' is not handling things, so never write that and update your IDE templates).
public static void CandidatesPartyList_JComboBox() {
try (Connection c = VotingSystem.con();
PreparedStatement ps = c.prepareStatement("SELECT * FROM partylist WHERE p_status = 'Active' ORDER BY p_name ASC");
ResultSet rs = ps.executeQuery()) {
candidates_filter_partylist.removeAllItems();
candidates_filter_partylist.addItem("- Select PartyList -");
while (rs.next()) {
candidates_filter_partylist.addItem(rs.getString("p_name"));
}
} catch (SQLException e) {
throw new RuntimeException("Unhandled", e);
}
}

Java Class error in Eclipse

Giving error at line 12 "This method must return a result of type Boolean".
I have written my code in try catch block. If a move the resultset operation below the catch block then the error appears on resultset object.
Where am I wrong, Please answer me. Thank you.
public class LoginService {
public Boolean verifyLogin(LoginModel loginModel) { // In this line it is
// giving error
DbConnection dbConnection = new DbConnection();
ResultSet rs;
try {
Connection con = dbConnection.getConnection();
System.out.println("Connection Established");
String query = "select * from login where tenantid=? and userid=? and password=?";
PreparedStatement ps = con.prepareStatement(query);
ps.setInt(1, loginModel.getTenantid());
ps.setString(2, loginModel.getUserid());
ps.setString(3, loginModel.getPassword());
rs = ps.executeQuery();
if (rs.next()) {
System.out.println("User exists !!");
return true;
} else {
System.out.println("User does not exists !!");
return false;
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
}
}
When your code catches an exception you are simply printing the stacktrace and then allowing the function to continue.
However, after the catch blocks, you have no return statement, which is what the complaint is.
As others have mentioned, you're missing a return statement either in the catch blocks or after the catch blocks. Here's my boiler plate example of a function that returns a boolean:
bool foo()
{
bool result = false;
//do stuff, and set result to true at some point
return result;
}
This pattern is beneficial because it helps reduce the number of returns in your functions. There are some coding styles out there that won't allow more than 2 return statements in a function, for example.
Here it is applied to your function:
public Boolean verifyLogin(LoginModel loginModel) { // In this line it is
// giving error
Boolean result = false;
DbConnection dbConnection = new DbConnection();
ResultSet rs;
try {
Connection con = dbConnection.getConnection();
System.out.println("Connection Established");
String query = "select * from login where tenantid=? and userid=? and password=?";
PreparedStatement ps = con.prepareStatement(query);
ps.setInt(1, loginModel.getTenantid());
ps.setString(2, loginModel.getUserid());
ps.setString(3, loginModel.getPassword());
rs = ps.executeQuery();
if (rs.next()) {
System.out.println("User exists !!");
result = true; //--------------------This line changed!
} else {
System.out.println("User does not exists !!");
result = false; //-------------------This line changed!
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
return result;
}
You should return in catch blocks too. Or in finally block.
You need to add a return statement after your catch block.
Your method may throw an exception, in this case, the code that will be executed will be in the catch clauses.
Add a finally clause after the catch's with the desired value for when this happens.
The problem is that if an exception occurs, nothing is returned. I would suggest adding
return false;
to all of your catch blocks

Fail to cleanup java.sql.Statement on checked Exception

In my method show below find bug is specifying Fail to cleanup java.sql.Statement on checked Exception
public int updateSecurityCodeHistoryForMessage(String phone, String securityCodeHistoryId, String messageState, String messageId, String parentMessageId)
{
CaptivePortalLogger.appLog.error(MODULE+"Start : updateSecurityCodeHistoryForMessage::"+messageState);
int result=-1;
String query=null;
Connection con = null;
PreparedStatement pstmt =null;
try
{
CaptivePortalLogger.sysOut.debug(MODULE + " (Method : isSecurityCodeUsed) Available Connection : "+ CaptivePortalDBConnection.getNumIdleConnections());
CaptivePortalLogger.sysOut.debug(MODULE + " (Method : isSecurityCodeUsed) Active Connection : "+ CaptivePortalDBConnection.getNumActiveConnections() );
con = CaptivePortalDBConnection.getDataSource().getConnection();
CaptivePortalLogger.appLog.error(MODULE+" Before updateSecurityCodeHistoryForMessage into SendMessageAndReceiveReport: ");
query="UPDATE tblsecuritycodehistory SET messagestate = ?,messageid = ? WHERE securitycodehistoryid = ? AND mobileno = ?";
CaptivePortalLogger.appLog.debug(MODULE + "for updateSecurityCodeHistoryForMessage in SendMessageAndReceiveReport Query : "+ query);
pstmt = con.prepareStatement(query);
pstmt.setString(1,messageState); //<b>line 556</b>
pstmt.setString(2,messageId);
pstmt.setString(3,securityCodeHistoryId);
pstmt.setString(4,phone);
result = pstmt.executeUpdate();
CaptivePortalLogger.appLog.error(MODULE+" After updateSecurityCodeHistoryForMessage into SendMessageAndReceiveReport: result::"+result);
}
catch (Exception e) {
result = -1;
CaptivePortalLogger.traceLog.debug("Got an exception while updateSecurityCodeHistoryForMessage in SendMessageAndReceiveReport: ",e);
}
finally
{
CaptivePortalLogger.appLog.debug(MODULE+"Finally Start");
try
{
if(pstmt!=null)
pstmt.close();
if(con !=null)
con.close();
CaptivePortalLogger.sysOut.debug(MODULE + " (Method : updateSecurityCodeHistoryForMessage) Closing connections done ....");
}
catch(Exception e)
{
CaptivePortalLogger.traceLog.debug("Error in closing sqlReader.",e);
}
}
CaptivePortalLogger.appLog.error(MODULE+"End : updateSecurityCodeHistoryForMessage");
return result;
}
I find lots of links on stack but none of them able to solve my problem(may be i m not able to understand them properly). Any help will be appreciated.
Thanks in Advance..........
After updaing my finally block with a solution specfied by #Mark problem persists
finally
{
CaptivePortalLogger.appLog.debug(MODULE+"Finally Start");
try {
if(pstmt!=null)
pstmt.close();
} catch (Exception ex) {
// Log, ignore, etc
}
try {
if(con !=null)
con.close();
} catch (Exception ex) {
// Log, ignore, etc
}
CaptivePortalLogger.sysOut.debug(MODULE + " (Method : updateSecurityCodeHistoryForMessage) Closing connections done ....");
}
After using #Jon suggestion , my problem get resolved. finally resolved code is ::
public int updateSecurityCodeHistoryForMessage(String phone, String securityCodeHistoryId, String messageState, String messageId, String parentMessageId)
{
CaptivePortalLogger.appLog.error(MODULE+"Start : updateSecurityCodeHistoryForMessage::"+messageState);
int result=-1;
String query=null;
Connection con = null;
PreparedStatement pstmt =null;
try
{
CaptivePortalLogger.sysOut.debug(MODULE + " (Method : isSecurityCodeUsed) Available Connection : "+ CaptivePortalDBConnection.getNumIdleConnections());
CaptivePortalLogger.sysOut.debug(MODULE + " (Method : isSecurityCodeUsed) Active Connection : "+ CaptivePortalDBConnection.getNumActiveConnections() );
con = CaptivePortalDBConnection.getDataSource().getConnection();
CaptivePortalLogger.appLog.error(MODULE+" Before updateSecurityCodeHistoryForMessage into SendMessageAndReceiveReport: ");
query="UPDATE tblsecuritycodehistory SET messagestate = ?,messageid = ? WHERE securitycodehistoryid = ? AND mobileno = ?";
CaptivePortalLogger.appLog.debug(MODULE + "for updateSecurityCodeHistoryForMessage in SendMessageAndReceiveReport Query : "+ query);
try
{
pstmt = con.prepareStatement(query);
pstmt.setString(1,messageState);
pstmt.setString(2,messageId);
pstmt.setString(3,securityCodeHistoryId);
pstmt.setString(4,phone);
result = pstmt.executeUpdate();
}
catch(SQLException e1)
{
CaptivePortalLogger.traceLog.debug("Error in closing sqlReader.",e1);
}
finally{
if(pstmt!=null)
pstmt.close();
}
CaptivePortalLogger.appLog.error(MODULE+" After updateSecurityCodeHistoryForMessage into SendMessageAndReceiveReport: result::"+result);
}
catch (SQLException e2) {
result = -1;
CaptivePortalLogger.traceLog.debug("Got an exception while updateSecurityCodeHistoryForMessage in SendMessageAndReceiveReport: ",e2);
}
finally
{
CaptivePortalLogger.appLog.debug(MODULE+"Finally Start");
try
{
if(con !=null)
con.close();
CaptivePortalLogger.sysOut.debug(MODULE + " (Method : updateSecurityCodeHistoryForMessage) Closing connections done ....");
}
catch(SQLException e)
{
CaptivePortalLogger.traceLog.debug("Error in closing sqlReader.",e);
}
}
CaptivePortalLogger.appLog.error(MODULE+"End : updateSecurityCodeHistoryForMessage");
return result;
}
Look at this code:
if(pstmt!=null)
pstmt.close();
if(con !=null)
con.close();
Now consider that pstmt.close() can throw an exception... which means con.close() wouldn't be called.
If you're using Java 7, use a try-with-resources statement instead, but otherwise you should have a separate try/finally block for each resource.
try {
connection = ...;
try {
statement = ...;
} finally {
// Clean up statement
}
} finally {
// Clean up connection
}
I'd also strongly recommend against catching blanket Exception - it's better to catch specific exceptions which you can actually handle, and let other exceptions propagate up the stack. Also, you appear to be using integer values to signal success or failure of your method - that's not idiomatic Java; exceptions are preferred for error handling, in general.
The problem is that if pstmt.close() throws an Exception, then the connection is never closed.
Either do not close the statement in the finally (as drivers are required to close Statement objects if the Connection is closed), or put both in their own try..catch-block. Eg:
finally
{
CaptivePortalLogger.appLog.debug(MODULE+"Finally Start");
try {
if(pstmt!=null)
pstmt.close();
} catch (Exception ex) {
// Log, ignore, etc
}
try {
if(con !=null)
con.close();
} catch (Exception ex) {
// Log, ignore, etc
}
CaptivePortalLogger.sysOut.debug(MODULE + " (Method : updateSecurityCodeHistoryForMessage) Closing connections done ....");
}
Firebug is correct.
You should close all your SQL resources in a finally block, using individually wrapped calls to close methods.
You can do it with a utility class:
package persistence;
public class DatabaseUtils {
// similar methods for ResultSet and Connection
public static void close(Statement s) {
try {
if (s != null) {
s.close();
}
} catch (SQLException e) {
// Log the exception
}
}
}
Call the close method in a finally block in the method that created the resource.
Try to cleanup /close resource in separate try/catch/finally block otherwise if any one throw an exception then rest of will be remain unclosed.

Handling all exceptions when executing SQL in Java

There are many steps involved in executing one SQL statement in Java:
Create connection
Create statement
Execute statement, create resultset
Close resultset
Close statement
Close connection
At each of these steps SQLException can be thrown. If we to handle all exception and release all the resources correctly, the code will will look like this with 4 levels of TRY stacked on the top of each other.
try {
Connection connection = dataSource.getConnection();
try {
PreparedStatement statement = connection.prepareStatement("SELECT 1 FROM myTable");
try {
ResultSet result = statement.executeQuery();
try {
if (result.next()) {
Integer theOne = result.getInt(1);
}
}
finally {
result.close();
}
}
finally {
statement.close();
}
}
finally {
connection.close();
}
}
catch (SQLException e) {
// Handle exception
}
Can you propose a better (shorter) way to execute a statement while still release all the consumed resources?
If you are using Java 7, the try with resources statement will shorten this quite a bit, and make it more maintainable:
try (Connection conn = ds.getConnection(); PreparedStatement ps = conn.prepareStatement(queryString); ResultSet rs = ps.execute()) {
} catch (SQLException e) {
//Log the error somehow
}
Note that closing the connection closes all associated Statements and ResultSets.
Check out Apache Commons DbUtils, and in particular the closeQuietly() method. It will handle the connection/statement/result set closing correctly, including the cases where one or more are null.
An alternative is Spring JdbcTemplate, which abstracts a lot of work away from you, and you handle your database queries in a much more functional fashion. You simply provide a class as a callback to be called on for every row of a ResultSet. It'll handle iteration, exception handling and the correct closing of resources.
I create a utility class with static methods I can call:
package persistence;
// add imports.
public final class DatabaseUtils {
// similar for the others Connection and Statement
public static void close(ResultSet rs) {
try {
if (rs != null) {
rs.close();
}
} catch (Exception e) {
LOGGER.error("Failed to close ResultSet", e);
}
}
}
So your code would be:
Integer theOne = null;
Connection connection = null;
PreparedStatement statment = null;
ResultSet result = null;
try {
connection = dataSource.getConnection();
statement = connection.prepareStatement("SELECT 1 FROM myTable");
result = statement.executeQuery();
while (result.next()) {
theOne = result.getInt(1);
}
} catch (SQLException e) {
// do something
} finally {
DatabaseUtils.close(result);
DatabaseUtils.close(statement);
DatabaseUtils.close(connection);
}
return theOne;
I'd recommend instantiating the Connection outside this method and passing it in. You can handle transactions better that way.
Connection connection = null;
PreparedStatement statement = null;
ResultSet result = null;
try {
connection = dataSource.getConnection();
statement = connection.prepareStatement("SELECT 1 FROM myTable");
result = statement.executeQuery();
if (result.next()) {
Integer theOne = result.getInt(1);
}
}
catch (SQLException e) { /* log error */ }
finally {
if (result != null) try { result.close(); } catch (Exception e) {/*log error or ignore*/}
if (statement != null) try { statement.close(); } catch (Exception e) {/*log error or ignore*/}
if (connection != null) try { connection.close(); } catch (Exception e) {/*log error or ignore*/}
}
Just close the Connection, this releases all resources*. You don't need to close Statement and ResultSet.
*just make sure you don't have any active transactions.
Your code can be shortened and written in this way...
Connection connection = dataSource.getConnection();
PreparedStatement statement = null;
ResultSet result = null;
try {
statement= connection.prepareStatement("SELECT 1 FROM myTable");
result = statement.executeQuery();
if (result.next()) {
Integer theOne = result.getInt(1);
}
} catch (SQLException e) {
// Handle exception
} finally {
if(result != null) result.close();
if(statement != null) statement.close();
if(connection != null) connection.close();
}

Categories