Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java Iterator backed by a ResultSet

I've got a class that implements Iterator with a ResultSet as a data member. Essentially the class looks like this:

public class A implements Iterator{     private ResultSet entities;     ...     public Object next(){         entities.next();         return new Entity(entities.getString...etc....)     }      public boolean hasNext(){         //what to do?     }     ... } 

How can I check if the ResultSet has another row so I can create a valid hasNext method since ResultSet has no hasNext defined itself? I was thinking doing SELECT COUNT(*) FROM... query to get the count and managing that number to see if there's another row but I'd like to avoid this.

like image 927
Jordan Messina Avatar asked Dec 08 '09 21:12

Jordan Messina


People also ask

How do you iterate over a ResultSet?

Iterating the ResultSet To iterate the ResultSet you use its next() method. The next() method returns true if the ResultSet has a next record, and moves the ResultSet to point to the next record. If there were no more records, next() returns false, and you can no longer.

What is ResultSet getString ()?

Retrieves the Statement object that produced this ResultSet object. String. getString(int columnIndex) Retrieves the value of the designated column in the current row of this ResultSet object as a String in the Java programming language.

Can we use ResultSet after closing connection?

Once the connection is closed you can no longer use any of the resources (statements, prepared statements, result sets), all of them are automatically closed. So you need to do all of your processing while the resources are open.


2 Answers

This is a bad idea. This approach requires that the connection is open the whole time until the last row is read, and outside the DAO layer you never know when it will happen, and you also seem to leave the resultset open and risk resource leaks and application crashes in the case the connection times out. You don't want to have that.

The normal JDBC practice is that you acquire Connection, Statement and ResultSet in the shortest possible scope. The normal practice is also that you map multiple rows into a List or maybe a Map and guess what, they do have an Iterator.

public List<Data> list() throws SQLException {     List<Data> list = new ArrayList<Data>();      try (         Connection connection = database.getConnection();         Statement statement = connection.createStatement("SELECT id, name, value FROM data");         ResultSet resultSet = statement.executeQuery();     ) {         while (resultSet.next()) {             list.add(map(resultSet));         }     }      return list; }  private Data map(ResultSet resultSet) throws SQLException {     Data data = new Data();      data.setId(resultSet.getLong("id"));     data.setName(resultSet.getString("name"));     data.setValue(resultSet.getInteger("value"));     return data; } 

And use it as below:

List<Data> list = dataDAO.list();  int count = list.size(); // Easy as that. Iterator<Data> iterator = list.iterator(); // There is your Iterator. 

Do not pass expensive DB resources outside the DAO layer like you initially wanted to do. For more basic examples of normal JDBC practices and the DAO pattern you may find this article useful.

like image 176
BalusC Avatar answered Sep 22 '22 17:09

BalusC


You can get out of this pickle by performing a look-ahead in the hasNext() and remembering that you did a lookup to prevent consuming too many records, something like:

public class A implements Iterator{     private ResultSet entities;     private boolean didNext = false;     private boolean hasNext = false;     ...     public Object next(){         if (!didNext) {             entities.next();         }         didNext = false;         return new Entity(entities.getString...etc....)     }      public boolean hasNext(){         if (!didNext) {             hasNext = entities.next();             didNext = true;         }         return hasNext;     }     ... } 
like image 27
rsp Avatar answered Sep 20 '22 17:09

rsp