Я соглашаюсь с compacity решения для переключателя, но IMO Вы угон переключателя здесь.
цель переключателя состоит в том, чтобы иметь отличающийся обработка в зависимости от значения.
, Если бы необходимо было объяснить алгоритм в псевдокоде, Вы использовали бы если потому что, семантически, вот что это значит: , если whatever_error делают это ...
Поэтому, если Вы не намереваетесь когда-нибудь изменить свой код для имения определенного кода для каждой ошибки, я использовал бы если .
Это плохая идея. Этот подход требует, чтобы соединение было открыто все время, пока не будет прочитана последняя строка, а за пределами уровня DAO вы никогда не знаете, когда это произойдет, и вы также, кажется, оставляете набор результатов открытым и рискуете утечками ресурсов и сбоями приложения в случае время ожидания соединения истекло. Вы не хотите этого.
Обычная практика JDBC заключается в том, что вы приобретаете Connection
, Statement
и ResultSet
в кратчайшей возможной области. Обычной практикой также является отображение нескольких строк в List
или, может быть, в Map
и угадайте, что у них действительно есть 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;
}
И используйте его, как показано ниже:
List<Data> list = dataDAO.list();
int count = list.size(); // Easy as that.
Iterator<Data> iterator = list.iterator(); // There is your Iterator.
Не передавайте дорогостоящие ресурсы БД за пределы уровня DAO, как вы изначально хотели. Для более простых примеров обычных практик JDBC и шаблона DAO вы можете найти эту статью полезной.
Похоже, вы застряли между предоставлением неэффективной реализации hasNext
или выдача исключения о том, что вы не поддерживаете операцию.
К сожалению, бывают случаи, когда вы реализуете интерфейс, и вам не нужны все члены.
Ожидаете ли вы, что большая часть данных в вашем наборе результатов действительно будет использоваться? Если это так, предварительно закешируйте его. Это довольно просто, например, Spring
List<Map<String,Object>> rows = jdbcTemplate.queryForList(sql);
return rows.iterator();
Отрегулируйте по своему вкусу.
entity.next возвращает false, если строк больше нет, поэтому вы можете просто получить это возвращаемое значение и установить переменную-член, чтобы отслеживать статус для hasNext ().
Но для того, чтобы это работало, вам также потребуется какой-то метод инициализации, который считывает первую сущность и кэширует ее в классе. Затем при вызове next вам нужно будет вернуть ранее кэшированное значение и кэшировать следующее значение и т. Д.
Вы можете попробовать следующее:
public class A implements Iterator {
private ResultSet entities;
private Entity nextEntity;
...
public Object next() {
Entity tempEntity;
if ( !nextEntity ) {
entities.next();
tempEntity = new Entity( entities.getString...etc....)
} else {
tempEntity = nextEntity;
}
entities.next();
nextEntity = new Entity( entities.getString...ext....)
return tempEntity;
}
public boolean hasNext() {
return nextEntity ? true : false;
}
}
Этот код кэширует следующую сущность, а hasNext () возвращает истину, если кешированная сущность действительна, иначе возвращает ложь.
ResultSet имеет метод isLast (), который может удовлетворить ваши потребности. В JavaDoc говорится, что это довольно дорого, хотя и требует предварительного чтения. Есть большая вероятность, что он кэширует прогнозируемое значение, как и другие предложения.
Вы можете выйти из этого рассола, выполнив предварительный просмотр в hasNext ()
и вспомнив, что вы выполнили поиск, чтобы предотвратить потребление слишком большого количества записей, например:
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;
}
...
}
Там это пара вещей, которые вы можете сделать в зависимости от того, что вы хотите от своего класса A.