SQLException, ResultSet closed but I can figure out why - mysql

I'm having a problem with java.sql.ResultSet, I have a java.sql.PreparedStatement on which I run executeQuery() to return a ResultSet yet when I try to get the results from the query I'm getting an Exception thrown:
Exception: java.sql.SQLException Message: Operation not allowed after
ResultSet closed.
From searching online it looks like a ResultSet can end up being closed for a few reason:
The PreparedStatement object that generated it is closed.
The PreparedStatement object that generated it is re-executed.
The PreparedStatement object that generated it is used to retrieve the next result from a sequence of multiple results.
Closing the Connection which was used to generate the PreparedStatement.
I checked my code and do none of those things. Below is a snippet of the code that causes the problem:
PreparedStatement psAccountPartyIdByEmail = null;
....
try {
String [] nextLine;
while ((nextLine = reader.readNext()) != null) {
String email = nextLine[0];
.....
try {
if (psAccountPartyIdByEmail == null) {
psAccountPartyIdByEmail = session.connection().prepareStatement(SQL_GET_ACCOUNTPARTYID_BY_EMAILADDRESS);
}
psAccountPartyIdByEmail.setString(1, email);
ResultSet partyIds = psAccountPartyIdByEmail.executeQuery();
while (partyIds.next()) {
String partyId = partyIds.getString(1);
.....
}
} catch (SQLException e) {
Debug.logError(e, "Encountered SQLException while running group service.", MODULE);
}
}
} catch (IOException e) {
Debug.logError(e, "Problem reading line in file", MODULE);
}
The Exception is thrown when trying to execute: while (partyIds.next()) {
Like I stated I never close the connection or statement and as you can see I don't reuse the statement prior to trying to view my result.
Thanks for he help...
Marc

I don't know if this will fix this problem but you can/should move
if (psAccountPartyIdByEmail == null) {
psAccountPartyIdByEmail = session.connection().prepareStatement(SQL_GET_ACCOUNTPARTYID_BY_EMAILADDRESS);
}
outside of the while loop.
Also, close the ResultSet after you've processed the rows.
Then, when you're all done close your statement and connection.

Related

try-with-resources and catching Exceptions which are both thrown during normal execution and autoClose

I am pondering for a while with the following code:
try (Connection conn = dbHandler.getConnection()) {
// do something with the connection
dbConn.commit();
} catch (SQLException e) {
System.err.println("Too bad!");
e.printStackTrace();
}
Consider my application needs to be resilient to some SQL locking/dead-lock situations, so I would need to do some specific handling inside of the catch block. However, I cannot easily identify, if the exception was thrown during the "do something" part of my code or during autoClose(). And of course, each JDBC driver throws slightly different exceptions and if you throw JDBI in the mix, it gets even more complicated. So you can't really rely on different catch clauses do precisely identify, when the exception got thrown.
The only solution I could come up with is this code:
boolean finishedProcessing = false;
try (Connection conn = dbHandler.getConnection()) {
// do something with the connection
dbConn.commit();
finishedProcessing = true;
} catch (SQLException e) {
if (finishedProcessing) {
// this is an exception during autoClose
System.err.println("Too bad!");
e.printStackTrace();
} else {
// handle rollback cases, retries etc
System.err.println("SQL recovery performed.");
throw e;
}
}
Now the same issue comes up with IOExceptions for File* operations and probably in many other cases.
To be honest, I am just hoping I missed something completely obvious and I appreciate any insight from the Java experts out here.
As stated above, the only solution I found so far is introducing state-variables into the code, which doesn't really make sense to me.
I am fully aware of suppressing exceptions from the autoClose process, when an exception got thrown by the try block, however, as stated above the same kind of exception can be thrown, suppressed and both.
Don't use try-with-resources and add a finally block.
Connection conn = null;
try {
conn = dbHandler.getConnection()
// do something with the connection
dbConn.commit();
}
catch (SQLException e) {
// Handle rollback cases, retries, etc.
System.err.println("SQL recovery performed.");
e.printStackTrace();
}
finally {
if (conn != null) {
try {
conn.close();
}
catch (SQLException xSql) {
System.out.println("Failed to close database connection.");
xSql.printStackTrace();
}
}
}

Caught a throwable exception during processing Closed Resultset: next

So I did try checking for answers before I could ask this question again, I'm getting a closed ResultSet exception for my code below.
The same code worked on development environment when tested for a small set of records. But on QA environment the exception is encountered for 200-300 records being fetched by the query as well.
My question is, if there is no close statement or close connection code why is the closed resultset exception thrown at the While loop in the code below?
public void extractRecordsAndUpdateData() throws Throwable {
ConnectionManager mgr =null;
/*
* Some authentication code here for user authentication to allow access in the application
*/
Connection c = null;
try {
mgr = mServiceLocator.getConnectionManager();
}
catch (Exception newex) {
newex.printStackTrace();
customLogWriter.logEntry("Got a Exception during authentication " + newex.getMessage());
}
PreparedStatement pSql = null;
ResultSet myResultSet = null;
try {
c = mgr.getConnection(mgr.getSiteName());
pSql = c.prepareStatement(extractSQL); // extractSQL is a simple select statement fetching records from DB to be processed in the while loop below.
myResultSet = pSql.executeQuery();
}catch(SQLException ex){customLogWriter.logEntry("Error " + ex.getMessage());}
List<List> outerList=new ArrayList<List>();
while (myResultSet.next()) // Exception encountered on this line of code
{
/*Do some processing*/
}
customLogWriter.close();
}
Poorly structured exception handling. The ResultSet.next() loop should be inside the try block. You should only have one try and one catch (SQLException ...) here.
Don't write code like this. Code that depends on the success of code in a prior try block should be inside that try block.

EntityFramework exception: How can i see the real query

Sometimes i have an EntityFramework exception where calling SaveChanges.
I see this kind of message: "An error occurred while updating the entries. See the inner exception for details."
I have logged the stack trace, the inner exception and stuff but there is no clear explanation of the problem. I would like to see the real query (it is a mysql database), with the parameters. Do you know how i can see or log the real query ?
Thanks
You can use DbEntityValidationException handler which will let you know what was wrong precisely.
try{
//Your code here
}
catch (DbEntityValidationException ex)
{
var errorMessages = ex.EntityValidationErrors
.SelectMany(x => x.ValidationErrors)
.Select(x => x.ErrorMessage);
var fullMessageError = string.Join("; ", errorMessages);
var exceptionMessage = string.Concat(ex.Message, "Exact Message " + fullMessageError);
}
catch (Exception ex)
{
//General Exception here
}
You can set log property of dbContext.Database and log the actual queries generated by EF.
using (var context = new MyDBContext())
{
context.Database.Log = Console.Write; // This is where you setup where to log queries
// Your code here...
}
There is a detailed documentation on MSDN https://msdn.microsoft.com/en-us/data/dn469464.aspx

Null pointer when trying to do rewriteBatchedStatements for MySQL and Java

I am trying to do batch inserts into mysql at very high rates. I wanted to try the rewriteBatchedStatements config option as I have read it can make significantly affect performance. When I add the option however I get the following exception:
java.lang.NullPointerException
at com.mysql.jdbc.PreparedStatement.computeMaxParameterSetSizeAndBatchSize(PreparedStatement.java:1694)
at com.mysql.jdbc.PreparedStatement.computeBatchSize(PreparedStatement.java:1651)
at com.mysql.jdbc.PreparedStatement.executeBatchedInserts(PreparedStatement.java:1515)
at com.mysql.jdbc.PreparedStatement.executeBatch(PreparedStatement.java:1272)
at com.zaxxer.hikari.proxy.StatementProxy.executeBatch(StatementProxy.java:116)
at com.zaxxer.hikari.proxy.PreparedStatementJavassistProxy.executeBatch(PreparedStatementJavassistProxy.java)
This is my code that does the inserts:
try (Connection connection = DBUtil.getInstance().getConnection();
PreparedStatement preparedStatement = connection.prepareStatement(query)) {
connection.setAutoCommit(false);
for (TransactionBatch batch : batches) {
try {
preparedStatement.setString(1, batch.getDeviceID());
preparedStatement.setBinaryStream(2, new ByteArrayInputStream(dataArray));
preparedStatement.addBatch();
} catch (Exception e) {
e.printStackTrace();
}
}
preparedStatement.executeBatch();
} catch (Exception e) {
e.printStackTrace();
}
This is my jdbc url:
jdbc:mysql://url:port/tableName?user=userame&password=password&useServerPrepStmts=false&rewriteBatchedStatements=true
Also I am using HikariCP as my connection pool.
EDIT: Update - looks like the problem relates to having a varbinary(10000) column in the table
The solution was to stop using:
preparedStatement.setBinaryStream(inputstream)
instead I used
preparedStatement.setBytes(byte[])
In order to rewrite it must need to calculate the total size which it can't do upfront from an input stream. It is working great now and my write speeds are awesome!

calling ExecuteReader() from catch block

I have the following code and when exception happens the ExecuteReader() in Catch block will hang the app.
My question is why the hang? I can't perform query inside of Catch block if query exception happens in general?
Try {
// some SQL queries
}
catch (SqlException odbcEx) {
// do some queries with IDbCommand::ExecuteReader()
}
catch (Exception ex) {
// Handle generic ones here.
}
Thanks,
The ExecuteReader() keeps hold of your SQL connection. What you want to do is wrap a using statement round it. Also, you can't perform a SQL query because you have essentially errored and lost scope of your SQL connection variable. If you want, you can do some further SQL in the exception block by instantiating a new instance of your reader and connection, however ideally close of your existing connection before doing so. If you use a datatable you won't keep hold of the SQL connection. Perhaps something to look at.
For example:
using (var conn = new SqlConnection("ConnectionString"))
{
try {
// some SQL queries
}
catch (SqlException odbcEx) {
// do some queries with IDbCommand::ExecuteReader()
}
catch (Exception ex) {
// Handle generic ones here.
}
finally {
conn.Close();
}
}
This way you are disposing of your connection and not keeping hold of it.