Getting error SQLServerException: The result set is closed - java

I have tried many ways but always i'm getting this error.
Actually i'm trying to access result set values from other class and for Database Query i have created a separate class.
Please do not mark this as previously asked because i got the solution only of single class.
This is my DBVerification class
public class DBVerification {
private static String DB_URL = PropertyManager.getInstance().getDB_URL();
private static String DB_USER= PropertyManager.getInstance().getDB_USER();
private static String DB_PASSWORD= PropertyManager.getInstance().getDB_PASSWORD();
private static String DBClass= PropertyManager.getInstance().getDBClass();
private static Connection connection;
public static ArrayList<ResultSet> executeStoredProcedure(String query) throws ClassNotFoundException, SQLException
{
ArrayList<ResultSet> resultset = new ArrayList<ResultSet>();
Class.forName(DBClass);
connection= DriverManager.getConnection(DB_URL, DB_USER, DB_PASSWORD);
CallableStatement cstmt = connection.prepareCall( "{ call " + query+" }" );
//System.out.println("{ call " + query+" }");
try {
boolean results = cstmt.execute();
int rsCount = 0;
do {
if(results) {
ResultSet rs = cstmt.getResultSet();
resultset.add(rs);
rsCount++;
System.out.println("RESULT SET #" + rsCount);
// rs.close();
}
System.out.println();
results = cstmt.getMoreResults();
} while(results);
//cstmt.getMoreResults(Statement.KEEP_CURRENT_RESULT);
//cstmt.close();
}
catch (Exception e) {
e.printStackTrace();
}
return resultset;
}
public static void closeDB() throws SQLException
{
connection.close();
}
}
This is my second class Reimbursement class
public class Reimbursement
{
ArrayList<ResultSet> result = DBVerification.executeStoredProcedure("getreimbursements");
for (ResultSet curInstance: result) {
if(result.indexOf(curInstance) == 0)
{
while(curInstance.next())
{
String branchName=curInstance.getString("BranchName");
String department=curInstance.getString("DepartmentName");
String employee=curInstance.getString("EmployeeName");
String title=curInstance.getString("Title");
String claimdate=ValueConverter.DateFormat(curInstance.getString("Date"));
}
curInstance.close();
}
if(result.indexOf(curInstance) == 1)
{
while(curInstance.next())
{
String category=curInstance.getString("Category");
String expensedate=ValueConverter.DateFormat(curInstance.getString("ExpenseDate"));
String description=curInstance.getString("Description");
String approvedby=curInstance.getString("ApprovedBy");
}
curInstance.close();
}
}
DBVerification.closeDB();
}
Please do not look for main method because this is for testing class so i'm already using this class in my xml file.
Please give me suggestion that what i'm doing wrong it give me error message that 'The result set is closed'.
Image of exception actually it is my test class so it will display error only in this form i have edited the line which was indicated
exception message

I think your problem might be as follows
you loop around the response to the call to your stored procedure, adding each result set from the call in to an arraylist
you return the arraylist back to your calling method and iterate over it
you try to process each resultset in turn.
Unfortunately, I think that the action of cstmt.getMoreResults() closes any open result sets before moving to the next one. What you are ending up with is an arraylist of closed ResultSet objects. When you try to read from them, you get the error saying "result set is already closed"
from the java docs
boolean getMoreResults()
throws SQLException
Moves to this Statement object's next result, returns true if it is a
ResultSet object, and implicitly closes any current ResultSet
object(s) obtained with the method getResultSet.

Related

SQLException: ResultSet closed

I'm trying to execute method which should create a new object with fields from database, and everytime i run this code im getting SQLException: ResultSet closed.
public DatabasedClient getDatabaseClient(int clientDatabaseid){
if(DatabaseClientUtil.isInDatabase(clientDatabaseid)){
return DatabaseClientUtil.getDBClient(clientDatabaseid);
}else{
try{
System.out.println("Trying to find user in db");
ResultSet rs = fbot.getStorage().query("select * from database_name where clientDBId = " + clientDatabaseid);
System.out.println("deb " + rs.getString("nick"));
while (rs.next()) {
DatabasedClient databasedClient = new DatabasedClient(clientDatabaseid);
databasedClient.setUid(rs.getString("uid"));
databasedClient.setNick(rs.getString("nick"));
databasedClient.setLastConnect(rs.getLong("lastConnected"));
databasedClient.setLastDisconnect(rs.getLong("lastDisconnect"));
databasedClient.setTimeSpent(rs.getLong("timeSpent"));
databasedClient.setLongestConnection(rs.getLong("longestConnection"));
return databasedClient;
}
} catch (SQLException e) {
e.printStackTrace();
}
}
return null;
}
}
Im using hikari, here are methods from AbstractStorage class
#Override
public void execute(String query) throws SQLException {
try (Connection connection = getConnection()){
connection.prepareStatement(query).executeUpdate();
}
}
#Override
public ResultSet query(String query) throws SQLException {
try (Connection connection = getConnection()) {
return connection.prepareStatement(query).executeQuery();
}
}
Screenshot from error
I hope someone will help me with this.
I think the exact error you are seeing is being caused by the following line of code:
System.out.println("deb " + rs.getString("nick"));
You are trying to access the result set before you advance the cursor to the first record. Also, your method getDatabaseClient is returning a single object which conceptually maps to a single expected record from the query. Hence, iterating once over the result set would seem to make sense. Taking all this into consideration, we can try the following:
try {
System.out.println("Trying to find user in db");
ResultSet rs = fbot.getStorage().query("select * from database_name where clientDBId = " + clientDatabaseid);
// do not access the result set here
if (rs.next()) {
DatabasedClient databasedClient = new DatabasedClient(clientDatabaseid);
databasedClient.setUid(rs.getString("uid"));
databasedClient.setNick(rs.getString("nick"));
databasedClient.setLastConnect(rs.getLong("lastConnected"));
databasedClient.setLastDisconnect(rs.getLong("lastDisconnect"));
databasedClient.setTimeSpent(rs.getLong("timeSpent"));
databasedClient.setLongestConnection(rs.getLong("longestConnection"));
return databasedClient;
}
} catch (SQLException e) {
e.printStackTrace();
}

use one jdbc connection class for all classes java

i have been using this JDBC conection in all of my class that had to run query but i created a new class which i dont want the constructor with a parameter of the DConnection from JDBC Class(main Database Class).
but i keep on getting NullPointExceptions. Can anyway figur out what that problem may be.
Thanks.
public class UsersDao {
// associating the Database Connection objekt
private DConnector connector;
private final Connection myConn;
// Constructor
public UsersDao() throws CZeitExceptionHand,SQLException {
myConn = connector.getConnenction();
}
public boolean updateUsers(String mitarb, int mid) throws SQLException{
// PreparedStatement myStmt = null;
Statement stmt = myConn.createStatement();
try {
String myStmt = "SELECT Bly "
+ "" + mid + ";";
return stmt.execute(myStmt);
} finally {
close(stmt);
}
}
Example like this Method which is working but in different class
String[][] getAllTheWorkers(DConnector connector) throws CZeitExceptionHand {
try {
Connection connect = connector.getConnenction();
Statement stmt = connect.createStatement();
ResultSet result = stmt.executeQuery("SELECT ");
result.last();
int nt = result.getRow();
result.beforeFirst();
}
return results;
} catch (SQLException e) {
throw new CZeitExceptionHand("Error: " + e);
}
}
The object does not seem to be initialized.
Can you please post which method is not working and from where it is invoked ?
P.S : Unable to add a comment - that is why have answered !

How do I call data from a table in a database into a java class in netbeans?

first time posting so sorry if my question is slightly strange.
So I have a project in school that requires us to create java classes using netbeans that open up a window with three options, check stock, purchase item and update stock.
We had a class called stockdata that held the details of 5 different items for us to use in our three classes to check, purchase and update items. The latest stage of our coursework requires us to create a derby database and enter the items into a table.
I have done this with no issues but I am having a problem getting the items from the table back into my classes to use. We were given the following code but I can't get it to work, even using the commented hints.
package stock;
// Skeleton version of StockData.java that links to a database.
// NOTE: You should not have to make any changes to the other
// Java GUI classes for this to work, if you complete it correctly.
// Indeed these classes shouldn't even need to be recompiled
import java.sql.*; // DB handling package
import java.io.*;
import org.apache.derby.drda.NetworkServerControl;
public class StockData {
private static Connection connection;
private static Statement stmt;
static {
// standard code to open a connection and statement to an Access database
try {
NetworkServerControl server = new NetworkServerControl();
server.start(null);
// Load JDBC driver
Class.forName("org.apache.derby.jdbc.EmbeddedDriver");
//Establish a connection
String sourceURL = "jdbc:derby://localhost:1527/"
+ new File("UserDB").getAbsolutePath() + ";";
connection = DriverManager.getConnection(sourceURL, "use", "use");
stmt = connection.createStatement();
} // The following exceptions must be caught
catch (ClassNotFoundException cnfe) {
System.out.println(cnfe);
} catch (SQLException sqle) {
System.out.println(sqle);
} catch (Exception e) {
System.out.println(e);
}
}
// You could make methods getName, getPrice and getQuantity simpler by using an auxiliary
// private String method getField(String key, int fieldNo) to return the appropriate field as a String
public static String getName(String key) {
try {
// Need single quote marks ' around the key field in SQL. This is easy to get wrong!
// For instance if key was "11" the SELECT statement would be:
// SELECT * FROM Stock WHERE stockKey = '11'
ResultSet res = stmt.executeQuery("SELECT * FROM Stock WHERE stockKey = '" + key + "'");
if (res.next()) { // there is a result
// the name field is the second one in the ResultSet
// Note that with ResultSet we count the fields starting from 1
return res.getString(2);
} else {
return null;
}
} catch (SQLException e) {
System.out.println(e);
return null;
}
}
public static double getPrice(String key) {
// Similar to getName. If no result, return -1.0
return 0;
}
public static int getQuantity(String key) {
// Similar to getName. If no result, return -1
return 0;
}
// update stock levels
// extra is +ve if adding stock
// extra is -ve if selling stock
public static void update(String key, int extra) {
// SQL UPDATE statement required. For instance if extra is 5 and stockKey is "11" then updateStr is
// UPDATE Stock SET stockQuantity = stockQuantity + 5 WHERE stockKey = '11'
String updateStr = "UPDATE Stock SET stockQuantity = stockQuantity + " + extra + " WHERE stockKey = '" + key + "'";
System.out.println(updateStr);
try {
stmt.executeUpdate(updateStr);
} catch (SQLException e) {
System.out.println(e);
}
}
// close the database
public static void close() {
try {
connection.close();
} catch (SQLException e) {
// this shouldn't happen
System.out.println(e);
}
}
}
Sorry if this seems a stupid question but I am fairly new to Java and was making good progress until this roadblock.
Thanks in advance!
Alex
Searching for "java sql" on Google delivers this link: https://docs.oracle.com/javase/tutorial/jdbc/basics/processingsqlstatements.html
From a connection you can create a statement (you can find this in the link and in your code) , then fetch a result set and loop over that with rs.next(). That should get your started.
Of course you have to make sure that the driver and database are there/running, just saying...
Here netbeans has nothing to do with database. This is a Java-based integrated development environment(IDE) that will help you to reduce syntactic error.
public void dataAccess(){
try {
String connectionUrl = "suitable connection url as per your database";
Connection con = null;
Statement stmt = null;
ResultSet rs = null;
Class.forName("JDBC driver name as per your database");
con = DriverManager.getConnection(connectionUrl, userName, password);
String SQL = "SQL query as per your criteria";
stmt = con.createStatement();
rs = stmt.executeQuery(query);
while (rs.next()) {
// look into ResultSet api and use method as per your requirement
}
rs.close();
}
catch (Exception e) {
//log error message ;
}
}

SQLite JDBC get on resultset always returns null resp. 0

In the following code, I execute a query on a SQLite JDBC connection via the executeRestitutionalQuery(String query) method:
public static ArrayList<Metadata> findMetadata(String name, String text, String after, String before, String repPath)
throws SQLException, ClassNotFoundException {
ArrayList<Metadata> data = new ArrayList<Metadata>();
boolean needADD = false;
String query = "SELECT * from " + TABLE_NAME_METADATA;
...
query += " ORDER BY timestamp DESC;";
ResultBundle bundle = executeRestitutionalQuery(query);
ResultSet result = bundle.getResultSet();
while(result.next()){
Metadata metadata = new Metadata(result.getLong("id"), result.getString("name"), Timestamp.valueOf(result.getString("timestamp")),
result.getInt("filesNo"), result.getLong("size"), result.getString("description"), -1);
data.add(metadata);
}
closeStatementAndResultSet(bundle.getStatement(), bundle.getResultSet());
return data;
}
private static ResultBundle executeRestitutionalQuery(String query) throws SQLException, ClassNotFoundException{
Connection connection = null;
Statement statement = null;
ResultSet result = null;
ResultBundle bundle = null;
try{
connection = getConnection();
statement = connection.createStatement();
statement.executeUpdate(query);
connection.commit();
result = statement.executeQuery(query);
bundle = new ResultBundle(statement, result);
}finally{
if(connection != null){
try{
connection.close();
}catch (Exception e){
/* ignored */
}
}
}
return bundle;
}
private static void closeStatementAndResultSet(Statement statement, ResultSet result){
if(result != null){
try{
result.close();
}catch (Exception e){
// ignored
}
}
if(statement != null){
try{
statement.close();
}catch (Exception e){
// ignored
}
}
}
The ResultBundle class is just used to summarize the resultset and the statement. It looks like this:
public class ResultBundle {
private final Statement statement;
private final ResultSet result;
public ResultBundle(Statement statement, ResultSet result){
this.result = result;
this.statement = statement;
}
public Statement getStatement(){
return statement;
}
public ResultSet getResultSet(){
return result;
}
}
The problem is, that every call to result.getLong(), result.getString() etc. returns null resp. 0. I can't understand why. The queries should all be okay, as the code was running fine before I had to do some refactoring. Could the problem arise from the ResultBundle-class? What am I not seeing here?
Statements and ResultSets are "live" objects, living only as long as their connection. The executeRestitutionalQuery returns a ResultBundle, whose result and statement members are implicitly closed on return when the connection is closed in the finally block.
try {
...
}finally{
if(connection != null){
try{
connection.close(); // <---- here's the problem
}catch (Exception e){
/* ignored */
}
}
}
By the time, the caller of executeRestitutionalQuery can lay its hand on the resource bundle, the connection has been closed, and the result set is "dead".
I would say this is a bad design.
A better one would keep the SQL objects in tight scope, map results into a collection or object and immediately close all those scarce resources. Not only will the data be available to clients, but you'll avoid nasty problems with connection and cursors exhausted. It'll scale better, too.

why can't java see my mysql driver

I'm having trouble working out why java can't see my mysql driver:
I've downloaded the driver .jar from the mysql website
I've added the jar to my runtime classpath
I can confirm the jar is on the classpath, by printing out the relevant system property
But I'm still getting ClassNotFound Exceptions. Is there anything else I need to be doing?
class example:
package org.rcz.dbtest;
import java.sql.*;
public class DB {
private Connection connect = null;
private Statement stmt = null;
private PreparedStatement prepared = null;
private ResultSet rset = null;
private String driverClassName = "com.myqsl.jdbc.Driver";
private String jdbcUrl = "jdbc:mysql://localhost/ctic_local?user=root&password=server";
private String queryString;
public DB(String query)
{
System.out.println(System.getProperty("java.class.path"));
queryString = query;
}
public void readFromDatabase()
{
try
{
Class.forName(driverClassName);
connect = DriverManager.getConnection(jdbcUrl);
stmt = connect.createStatement();
rset = stmt.executeQuery(queryString);
writeResultSet(rset);
}
catch (ClassNotFoundException cex)
{
System.out.println("Could not find mysql class");
}
catch(SQLException sqex)
{
}
}
private void writeResultSet(ResultSet resultSet) throws SQLException {
// ResultSet is initially before the first data set
while (resultSet.next()) {
// It is possible to get the columns via name
// also possible to get the columns via the column number
// which starts at 1
// e.g. resultSet.getSTring(2);
String user = resultSet.getString("name");
String comment = resultSet.getString("comment");
System.out.println("User: " + user);
System.out.println("Comment: " + comment);
}
}
}
My main class simply passes the query into the DB class:
package org.rcz.dbtest;
import java.io.IOException;
public class Main {
public static void main(String[] args) throws IOException
{
String qstring = "SELECT * FROM comments";
new DB(qstring).readFromDatabase();
System.in.read();
}
}
You've a typo in the driver class name.
private String driverClassName = "com.myqsl.jdbc.Driver";
it should be
private String driverClassName = "com.mysql.jdbc.Driver";
// -------------------------------------^
Unrelated to the concrete problem, holding DB resources like Connection, Statement and ResultSet as an instance variable of the class is a bad idea. You need to create, use and close them in the shortest possible scope in a try-finally block to prevent resource leaking. See also among others this question/answer: When my app loses connection, how should I recover it?

Categories