public ResultSet getAllCustomer() throws SQLException{
//List L = new ArrayList();
try {
stm = con.prepareStatement("select * from customer");
resultSetSubject = stm.executeQuery();
while (resultSetCustomer.next()) {
//L.add(resultSetCustomer);
resultSetCustomer.getInt(1);
resultSetCustomer.getString(2);
//System.out.println(resultSetCustomer.getInt("id")+" "+resultSetCustomer.getString("name"));
}
} catch (Exception e) {
System.out.println(e);
}
return resultSetCustomer;
}
Let me brief, I am fetching all record from the customer table and returning as resultset. I am accessing returned resultset as
ResultSet rs = T.getAllCustomer();
System.out.println(rs.getInt("id")+" "+rs.getString("name"));
There are several issues in your code:
You are obtaining a ResultSet object, looping over all of the rows in it, getting the column values, and then returning this ResultSet object. By the time it is returned to the caller, it has already been consumed by the loop that processed the rows (this is the cause of the error in your question).
Don't return the ResultSet object, instead create a Customer entity class that maps to the data in the DB, and return an instance of Customer. Returning a ResultSet object is really bad as it doesn't give control over how the object is closed, nor does it make your code object-oriented.
You don't need to create a prepared statement if you don't have a parameterized query.
The Statement (and ResultSet) must be closed after done. You should wrap the code that processes the whole result in a try-with-resources statement.
Your code needed little amendment
1 > Ensure resultset variable you use are same as defined (one place its different in your code).
2> use only
public ResultSet getAllCustomer() throws SQLException{
try {
stm = con.prepareStatement("select * from customer");
resultSetCustomer = stm.executeQuery();
} catch (Exception e) {
System.out.println(e);
}
return resultSetCustomer;
}
3> Close your connection/resultset/statement in separate method otherwise you will get error. you can use as below
public void close() throws SQLException{
if (resultSetCustomer != null) {
resultSetCustomer .close();
}
if (stm !=null) {
stm.close();
}
}
4> use resultset(your resultset instance).next() while accessing
in my small test program I have some SQL Queries. The first SELECT * FROM kilometer; works properly and returns all the columns in the table. So in Java embedded, ResultSet rs = stmt.executeQuery("SELECT * FROM kilometer;"); returns an ResultSet which is not empty.
Now I wanted to get only the rows within a specific date. But my embedded query ResultSet rs = stmt.executeQuery("SELECT * FROM kilometer WHERE datum BETWEEN '2016-01-01' AND '2016-12-31';"); returns an empty ResultSet. But I've tested it online and it worked properly. Where is my mistake? I've consulted already some pages like this, but I can't find the mistake.
I am using SQLite 3.15.1 and Java SE 8.
Full java code:
public ArrayList<Strecke> getErgebnisse(final String startzeitpunkt, final String zielzeitpunkt) {
ArrayList<Strecke> strecken = new ArrayList<>();
try {
try {
if (connection != null) {
}
connection = DriverManager.getConnection("jdbc:sqlite:" + DB_PATH);
if (!connection.isClosed())
} catch (SQLException e) {
throw new RuntimeException(e);
}
Statement stmt = connection.createStatement();
ResultSet rs = stmt.executeQuery("SELECT * FROM kilometer WHERE datum BETWEEN '2016-01-01' AND '2016-12-31';");
while (rs.next()) {
strecken.add(new Strecke(Instant.ofEpochMilli(rs.getDate("datum").getTime()).atZone(ZoneId.systemDefault()).toLocalDate(), rs.getString("startort"), rs.getString("zielort"), rs.getDouble("kilometer")));
}
rs.close();
connection.close();
} catch (SQLException e) {
e.printStackTrace();
}
return strecken;
}
First of all I would recommend that you use prepared statements while executing your queries instead of passing the query directly as a string......secondly I believe the problem here is that you are passing the date as a string in quotes and not a date.....I think that is the issue here. You would need to use sqllites datetime functions for this....
Overview: Trying to connect to a MS Access DB to return a result set into a jtable.
Issue: java null pointer exception
Code:
package sundata;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
public class Database {
public String strMIGID;
public String strEBID;
public String strSUN;
public String[][] objIDList;
//CONNECTION INFO
private Connection con;
private String strDBCon="jdbc:ucanaccess://C:/Users/Luke/Documents/MainDB.mdb";
public String strEXMessage;
public int CreateConnection(){
try{
Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");
con = DriverManager.getConnection(strDBCon);
return 1;
}catch(Exception ex){
ex.printStackTrace();
strEXMessage=ex.getMessage();
return 2;
}
}
public int CloseConnection(){
try{
con.close();
return 1;
}catch(Exception ex){
ex.printStackTrace();
strEXMessage=ex.getMessage();
return 2;
}
}
public int GetMIGIDRecord(String strMIGIDRef){
try{
System.out.println("Connecting to database using MIGID");
String strSQLString = "Select * from tblSuppliersData where Supplier1 = ?";
PreparedStatement preStatement = con.prepareStatement(strSQLString, ResultSet.TYPE_SCROLL_INSENSITIVE,ResultSet.CONCUR_READ_ONLY);
//SETTING FIRST CONDITION OF PREPARED STATEMENT IE ?
preStatement.setString(1, strMIGIDRef);
//EXECUTE QUERY
preStatement.executeQuery();
//RETURNS QUERY RESULTS INTO RESULT SET
ResultSet rs = preStatement.getResultSet();
//CHECK TO MAKE SURE SOME RECORDS ARE RETURNED
rs.last();
//IF CHECKS TO MAKE SURE RECORDS
if(rs.getRow()==0){
rs.close();
preStatement.close();
return 3;
}
//RECORDS NUMBER OF RECORDS
int iNoRecords = rs.getRow();
//CREATING 2D ARRAY WITH NO RECORDS (ROWS) AND TWO COLUMNS
String strTempdata[][] = new String [iNoRecords][3];
//MOVES BACK TO BEFORE FIRST RECORD
rs.beforeFirst();
//TRANSPOSES RS IN TO ARRAY
int i = 0;
while (rs.next()){
strTempdata[i][0]= rs.getString("MIGID");
strTempdata[i][1]= rs.getString("EBID");
strTempdata[i][2]= rs.getString("SUN");
i++;
}
objIDList = strTempdata;
//CLOSES CONNECTIONS
rs.close();
preStatement.close();
System.out.println("Connection complete");
return 1;
}catch(Exception ex){
ex.printStackTrace();
strEXMessage=ex.getMessage();
return 2;
}
}
I have a form that grabs the strMIGIDREF which I can paste code from if needs be, but I think it's not the issue here.
This is the error I'm getting, I've pasted the first bit and can paste more if required.
Connecting to database using MIGID
java.lang.NullPointerException
at sundata.Database.GetMIGIDRecord(Database.java:63)
at sundata.MainForm.MIGIDSearch(MainForm.java:141)
at sundata.MainForm.jmenuMIGIDSearchActionPerformed(MainForm.java:337)
at sundata.MainForm.access$000(MainForm.java:6)
at sundata.MainForm$1.actionPerformed(MainForm.java:58)
at javax.swing.AbstractButton.fireActionPerformed(AbstractButton.java:2018)
Line 63 is
//CHECK TO MAKE SURE SOME RECORDS ARE RETURNED
rs.last();
I have tried a number of solutions I've found on Google and no joy as of yet. I have tried a test bit of code that checks connections and such and that seemed to work fine it's just when I'm trying use preparedstatement it seems to go a miss.
ResultSet rs = preStatement.getResultSet(); just keeps saying it's value is null and so is getMaxRows.
I'm using Netbeans IDE 7.4 and JAVA SE SDK 7
You are getting a NullPointerException because you are mis-using the executeQuery method:
//EXECUTE QUERY
preStatement.executeQuery();
//RETURNS QUERY RESULTS INTO RESULT SET
ResultSet rs = preStatement.getResultSet();
The first line of code executes the SQL query and returns a ResultSet object, which you simply discard (because you don't assign it to anything). The second line of code attempts to retrieve the ResultSet for the PreparedStatement, but it has already been retrieved (and discarded) by the previous line, so getResultSet returns null.
Instead, you should simply do
ResultSet rs = preStatement.executeQuery();
Additional notes:
Omit the Class.forName("sun.jdbc.odbc.JdbcOdbcDriver"); statement because (1) It is irrelevant: UCanAccess does not use ODBC, and (2) Class.forName statements are almost never required any more (and UCanAccess doesn't need one at all).
Don't use rs.last() to test if rows were returned. Instead, simply call rs.next() immediately after the ResultSet is returned. If rs.next() returns true then the ResultSet contains rows (and you are now pointing at the first one). If rs.next() returns false then no rows were returned. rs.last() followed by rs.beforeFirst() will not work correctly with the default ResultSet type, which is ResultSet.TYPE_FORWARD_ONLY.
I am trying to create a simple web app that saves user data from a form to a database and reads the content of the database back to browser upon request. Following are the functions I have written so far.
connectToDB() // connects to database
addEmployee() // adds employee to database
displayEmployee() // returns a resultSet
isExisted(int staffID) // checks if the staff already exists
Database connection function:
public void connectToDB(){
try{
// load Apache derby driver
Class.forName("org.apache.derby.jdbc.EmbeddedDriver");
} catch(ClassNotFoundException e) {
System.err.println(e);
}
try{
connection = DriverManager.getConnection(DBNAME, USERNAME, PASSWORD);
} catch(SQLException e){
System.err.println(e);
}
} // end connectToDB
Display Employee function:
public ResultSet displayEmployee(){
connectToDB();
ResultSet result = null;
try{
Statement stmt = connection.createStatement();
String query = "SELECT * FROM APP.ADDRESSBOOK";
result = stmt.executeQuery(query);
} catch(SQLException e) {
System.err.println(e);
}
return result;
}
Check if employee exists:
public boolean isExisted(int StaffID){
connectToDB();
try{
Statement stmt = connection.createStatement();
String query = "SELECT StaffNum FROM APP.ADDRESSBOOK WHERE StaffNum = " + staff_number;
ResultSet result = stmt.executeQuery(query);
while(result.next()){
int temp = result.getInt(1);
if(temp == staff_number){return true;}
}
} catch(SQLException e) {
System.err.println(e);
}
return false;
}
As you can see, if you compare the displayEmployee() and isExisted(), I am repeating mysel. Both the function works but I am looking to refactor the code. In those function I havent closed the connection. If there were 20 functions in the web app that connects to the database my code would stink.
I am looking something like this:
* THIS CODE DOESNT WORK ******
private Statement queryDB(query){
connectToDB();
Statement stmt;
try{
stmt = connection.createStatement();
} catch(SQLException e) {
System.err.println(e);
}
return stmt;
// code for closing connection
}
public ResultSet DisplayEmployee(){
String query = "SELECT * FROM APP.ADDRESSBOOK";
Statement stmt = queryDB(query);
ResultSet result = stmt.executeQuery(query);
return result;
}
Thanks.
Using raw JDBC produces a lot of unsightly boilerplate code. One solution is to use Spring JDBC Template.
In addition you will get the sql exception hierarchy which will manage the underlying JDBC exceptions automatically as runtime exceptions.
For more see:
Introduction to Spring Framework JDBC
A couple of comments:
The catch statement of ClassNotFoundException should throw an exception and shouldn't continue further.
It is not a good idea to return resultsets from a method that obtained them upon statement execution, since it is the responsibility of that method to close it. Instead, you should either read out the results into objects or cache them into CachedRowSet if your downstream functions expect a resultset.
The connectToDB method should return a successful connection or throw exception.
You could write a method that takes in an SQL query and return the results as objects so that this method can be used for retrieving based on different criteria as long you are retrieving the objects of same type.
isExisted is using staff_number which I think you intend it to be staffID. If you found a row with this value, then there is no need to check if the result set contained the row with this value, right?
My two cents!
As soon as my code gets to my while(rs.next()) loop it produces the ResultSet is closed exception. What causes this exception and how can I correct for it?
EDIT: I notice in my code that I am nesting while(rs.next()) loop with another (rs2.next()), both result sets coming from the same DB, is this an issue?
Sounds like you executed another statement in the same connection before traversing the result set from the first statement. If you're nesting the processing of two result sets from the same database, you're doing something wrong. The combination of those sets should be done on the database side.
This could be caused by a number of reasons, including the driver you are using.
a) Some drivers do not allow nested statements. Depending if your driver supports JDBC 3.0 you should check the third parameter when creating the Statement object. For instance, I had the same problem with the JayBird driver to Firebird, but the code worked fine with the postgres driver. Then I added the third parameter to the createStatement method call and set it to ResultSet.HOLD_CURSORS_OVER_COMMIT, and the code started working fine for Firebird too.
static void testNestedRS() throws SQLException {
Connection con =null;
try {
// GET A CONNECTION
con = ConexionDesdeArchivo.obtenerConexion("examen-dest");
String sql1 = "select * from reportes_clasificacion";
Statement st1 = con.createStatement(
ResultSet.TYPE_SCROLL_INSENSITIVE,
ResultSet.CONCUR_READ_ONLY,
ResultSet.HOLD_CURSORS_OVER_COMMIT);
ResultSet rs1 = null;
try {
// EXECUTE THE FIRST QRY
rs1 = st1.executeQuery(sql1);
while (rs1.next()) {
// THIS LINE WILL BE PRINTED JUST ONCE ON
// SOME DRIVERS UNLESS YOU CREATE THE STATEMENT
// WITH 3 PARAMETERS USING
// ResultSet.HOLD_CURSORS_OVER_COMMIT
System.out.println("ST1 Row #: " + rs1.getRow());
String sql2 = "select * from reportes";
Statement st2 = con.createStatement(
ResultSet.TYPE_SCROLL_INSENSITIVE,
ResultSet.CONCUR_READ_ONLY);
// EXECUTE THE SECOND QRY. THIS CLOSES THE FIRST
// ResultSet ON SOME DRIVERS WITHOUT USING
// ResultSet.HOLD_CURSORS_OVER_COMMIT
st2.executeQuery(sql2);
st2.close();
}
} catch (SQLException e) {
e.printStackTrace();
} finally {
rs1.close();
st1.close();
}
} catch (SQLException e) {
} finally {
con.close();
}
}
b) There could be a bug in your code. Remember that you cannot reuse the Statement object, once you re-execute a query on the same statement object, all the opened resultsets associated with the statement are closed. Make sure you are not closing the statement.
Also, you can only have one result set open from each statement. So if you are iterating through two result sets at the same time, make sure they are executed on different statements. Opening a second result set on one statement will implicitly close the first.
http://java.sun.com/javase/6/docs/api/java/sql/Statement.html
The exception states that your result is closed. You should examine your code and look for all location where you issue a ResultSet.close() call. Also look for Statement.close() and Connection.close(). For sure, one of them gets called before rs.next() is called.
You may have closed either the Connection or Statement that made the ResultSet, which would lead to the ResultSet being closed as well.
Proper jdbc call should look something like:
try {
Connection conn;
Statement stmt;
ResultSet rs;
try {
conn = DriverManager.getConnection(myUrl,"","");
stmt = conn.createStatement();
rs = stmt.executeQuery(myQuery);
while ( rs.next() ) {
// process results
}
} catch (SqlException e) {
System.err.println("Got an exception! ");
System.err.println(e.getMessage());
} finally {
// you should release your resources here
if (rs != null) {
rs.close();
}
if (stmt != null) {
stmt.close();
}
if (conn != null) {
conn.close();
}
}
} catch (SqlException e) {
System.err.println("Got an exception! ");
System.err.println(e.getMessage());
}
you can close connection (or statement) only after you get result from result set. Safest way is to do it in finally block. However close() could also throe SqlException, hence the other try-catch block.
I got same error everything was correct only i was using same statement interface object to execute and update the database.
After separating i.e. using different objects of statement interface for updating and executing query i resolved this error. i.e. do get rid from this do not use same statement object for both updating and executing the query.
Check whether you have declared the method where this code is executing as static. If it is static there may be some other thread resetting the ResultSet.
make sure you have closed all your statments and resultsets before running rs.next. Finaly guarantees this
public boolean flowExists( Integer idStatusPrevious, Integer idStatus, Connection connection ) {
LogUtil.logRequestMethod();
PreparedStatement ps = null;
ResultSet rs = null;
try {
ps = connection.prepareStatement( Constants.SCRIPT_SELECT_FIND_FLOW_STATUS_BY_STATUS );
ps.setInt( 1, idStatusPrevious );
ps.setInt( 2, idStatus );
rs = ps.executeQuery();
Long count = 0L;
if ( rs != null ) {
while ( rs.next() ) {
count = rs.getLong( 1 );
break;
}
}
LogUtil.logSuccessMethod();
return count > 0L;
} catch ( Exception e ) {
String errorMsg = String
.format( Constants.ERROR_FINALIZED_METHOD, ( e.getMessage() != null ? e.getMessage() : "" ) );
LogUtil.logError( errorMsg, e );
throw new FatalException( errorMsg );
} finally {
rs.close();
ps.close();
}
A ResultSetClosedException could be thrown for two reasons.
1.) You have opened another connection to the database without closing all other connections.
2.) Your ResultSet may be returning no values. So when you try to access data from the ResultSet java will throw a ResultSetClosedException.
It happens also when using a ResultSet without being in a #Transactional method.
ScrollableResults results = getScrollableResults("select e from MyEntity e");
while (results.next()) {
...
}
results.close();
if MyEntity has eager relationships with other entities. the second time results.next() is invoked the ResultSet is closed exception is raised.
so if you use ScrollableResults on entities with eager relationships make sure your method is run transactionally.
"result set is closed" happened to me when using tag <collection> in MyBatis nested (one-to-many) xml <select> statement
A Spring solution could be to have a (Java) Spring #Service layer, where class/methods calling MyBatis select-collection statements are annotated with
#Transactional(propagation = Propagation.REQUIRED)
annotations being:
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
this solution does not require to set the following datasource properties (i.e., in JBoss EAP standalone*.xml):
<xa-datasource-property name="downgradeHoldCursorsUnderXa">**true**\</xa-datasource-property>
<xa-datasource-property name="resultSetHoldability">**1**</xa-datasource-property>