Spec-Zone .ru
спецификации, руководства, описания, API
|
A FilteredRowSet
объект позволяет Вам сокращать число строк, которые видимы в a RowSet
возразите так, чтобы можно было работать с только данными, которые относятся для того, что Вы делаете. Вы решаете то, что ограничивает Вас, хотят установить на Ваших данных (как Вы хотите "фильтровать" данные), и примените тот фильтр к a FilteredRowSet
объект. Другими словами, FilteredRowSet
объект делает видимым только строки данных, которые соответствуют в пределах пределов, которые Вы устанавливаете. A JdbcRowSet
объект, у которого всегда есть соединение с его источником данных, может сделать эту фильтрацию с запросом к источнику данных, который выбирает только столбцы и строки, которые Вы хотите видеть. Запрос WHERE
пункт определяет критерии фильтрации. A FilteredRowSet
объект обеспечивает путь к разъединенному RowSet
объект сделать эту фильтрацию, не имея необходимость выполнять запрос на источнике данных, таким образом избегая имеющий необходимость получить соединение с источником данных и отправляющий запросы этому.
Например, предположите, что цепочка Перерыва на кофе кофеен выросла к сотням хранилищ всюду по Соединенным Штатам Америки, и все они перечисляются в вызванной таблице COFFEE_HOUSES
. Владелец хочет измерить успех только хранилищ в Калифорнии с приложением сравнения кофейни, которое не требует персистентного соединения с системой баз данных. Это сравнение будет смотреть на доходность продажи товаров против продажи напитков кофе плюс различные другие меры успеха, и это оценит Калифорнийские хранилища продажами напитка кофе, продажами товаров, и общим объемом продаж. Поскольку таблица COFFEE_HOUSES
имеет сотни строк, эти сравнения будут быстрее и легче, если искавший объем данных будет сокращен к только тем строкам где значение в столбце STORE_ID
указывает на Калифорнию.
Это - точно вид проблемы это a FilteredRowSet
возразите адресам, обеспечивая следующие возможности:
Следующие темы затрагиваются:
Установить критерии для который строки в a FilteredRowSet
объект будет видим, Вы определяете class, который реализует Predicate
интерфейс. Объект, создаваемый с этим class, инициализируется со следующим:
Отметьте, что диапазон значений является содержащим, означая, что значение на границе включается в диапазон. Например, если у диапазона есть верхний уровень 100 и нижний уровень 50, значение 50, как полагают, в пределах диапазона. Значение 49 не. Аналогично, 100 в пределах диапазона, но 101 не.
В соответствии со сценарием, где владелец хочет сравнить Калифорнийские хранилища, реализацию Predicate
интерфейс, который фильтрует для кофеен Перерыва на кофе, расположенных в Калифорнии, должен быть записан. Нет никого правильного способа сделать это, что означает, что есть большая широта в том, как реализация пишется. Например, Вы могли назвать class и его элементы вообще, Вы хотите и реализуете конструктора, и эти три оценивают методы всегда, который выполняет требуемые результаты.
Таблица, перечисляющая все кофейни, названные COFFEE_HOUSES
, имеет сотни строк. Чтобы сделать вещи более управляемыми, этот пример использует таблицу с гораздо меньшим количеством строк, которой является достаточно, чтобы демонстрировать, как фильтрация делается.
Значение в столбце STORE_ID
int
значение, которое указывает, между прочим, на состояние, в котором располагается кофейня. Значение, начинающееся 10, например, средства, что состоянием является Калифорния. STORE_ID
значения, начинающиеся 32, указывают на Орегон, и те, которые начинают 33, указывают на штат Вашингтон.
Следующий class StateFilter
реализации Predicate
интерфейс:
public class StateFilter implements Predicate { private int lo; private int hi; private String colName = null; private int colNumber = -1; public StateFilter(int lo, int hi, int colNumber) { this.lo = lo; this.hi = hi; this.colNumber = colNumber; } public StateFilter(int lo, int hi, String colName) { this.lo = lo; this.hi = hi; this.colName = colName; } public boolean evaluate(Object value, String columnName) { boolean evaluation = true; if (columnName.equalsIgnoreCase(this.colName)) { int columnValue = ((Integer)value).intValue(); if ((columnValue >= this.lo) && (columnValue <= this.hi)) { evaluation = true; } else { evaluation = false; } } return evaluation; } public boolean evaluate(Object value, int columnNumber) { boolean evaluation = true; if (this.colNumber == columnNumber) { int columnValue = ((Integer)value).intValue(); if ((columnValue >= this.lo) && (columnValue <= this.hi)) { evaluation = true; } else { evaluation = false; } } return evaluation; } public boolean evaluate(RowSet rs) { CachedRowSet frs = (CachedRowSet)rs; boolean evaluation = false; try { int columnValue = -1; if (this.colNumber > 0) { columnValue = frs.getInt(this.colNumber); } else if (this.colName != null) { columnValue = frs.getInt(this.colName); } else { return false; } if ((columnValue >= this.lo) && (columnValue <= this.hi)) { evaluation = true; } } catch (SQLException e) { JDBCTutorialUtilities.printSQLException(e); return false; } catch (NullPointerException npe) { System.err.println("NullPointerException caught"); return false; } return evaluation; } }
Это - очень простая реализация, которая проверяет значение в столбец, определенный также colName
или colNumber
видеть, находится ли это в диапазоне lo
к hi
, включительно. Следующая строка кода, от FilteredRowSetSample
, создает фильтр, который позволяет только строки где STORE_ID
значение столбца указывает на значение между 10000 и 10999, который указывает на Калифорнийское расположение:
StateFilter myStateFilter = new StateFilter(10000, 10999, 1);
Отметьте что StateFilter
class, только определенный, применяется к одному столбцу. Возможно иметь это, применяются к двум или больше столбцам, делая каждый из массивов параметров вместо единственных значений. Например, конструктор для a Filter
объект мог быть похожим на следующее:
public Filter2(Object [] lo, Object [] hi, Object [] colNumber) { this.lo = lo; this.hi = hi; this.colNumber = colNumber; }
Первый элемент в colNumber
объект дает первый столбец, в котором значение будет проверено по первому элементу в lo
и первый элемент в hi
. Значение во втором столбце, обозначенном colNumber
будет проверен по вторым элементам в lo
и hi
, и так далее. Поэтому, число элементов в трех массивах должно быть тем же самым. Следующий код что реализация метода evaluate(RowSet rs)
мог бы быть похожим для a Filter2
объект, в котором параметры являются массивами:
public boolean evaluate(RowSet rs) { CachedRowSet crs = (CachedRowSet)rs; boolean bool1; boolean bool2; for (int i = 0; i < colNumber.length; i++) { if ((rs.getObject(colNumber[i] >= lo [i]) && (rs.getObject(colNumber[i] <= hi[i]) { bool1 = true; } else { bool2 = true; } if (bool2) { return false; } else { return true; } } }
Преимущество использования a Filter2
реализация состоит в том, что можно использовать параметры любого Object
введите и может проверить один столбец или многократные столбцы, не имея необходимость писать другую реализацию. Однако, следует передать Object
введите, что означает, что следует преобразовать тип примитива в Object
ввести. Например, если Вы используете int
значение для lo
и hi
, следует преобразовать int
оцените Integer
объект прежде, чем передать это конструктору. String
объекты уже Object
типы, таким образом, Вы не должны преобразовать их.
Ссылочная реализация для FilteredRowSet
интерфейс, FilteredRowSetImpl
, включает конструктора по умолчанию, который используется в следующей строке кода, чтобы создать пустое FilteredRowSet
объект frs:
.
FilteredRowSet frs = new FilteredRowSetImpl();
Реализация расширяется BaseRowSet
абстрактный class, таким образом, frs
объекту определили свойства значения по умолчанию в BaseRowSet
. Это означает это frs
с возможностью прокрутки, обновляем, не показывает удаленные строки, имеет включенную обработку escape, и так далее. Кроме того, потому что FilteredRowSet
интерфейс является подынтерфейсом CachedRowSet
, Joinable
, и WebRowSet
, frs
у объекта есть возможности каждого. Это может работать как разъединенный RowSet
возразите, может быть часть a JoinRowSet
объект, и может читать и записать себя в формате XML.
Отметьте: Альтернативно, можно использовать конструктора от WebRowSet
реализация Вашего драйвера JDBC. Однако, реализации RowSet
интерфейс будет отличаться от ссылочной реализации. У этих реализаций будут различные имена и конструкторы. Например, Oracle реализация драйвера JDBC WebRowSet
интерфейс называют oracle.jdbc.rowset.OracleWebRowSet
.
Можно использовать экземпляр RowSetFactory
, который создается из class RowSetProvider
, создать a FilteredRowSet
объект. См. Используя Интерфейс RowSetFactory в Использовании Объектов JdbcRowSet для получения дополнительной информации.
Как другой разъединенный RowSet
объекты, frs
объект должен заполнить себя с данными из источника табличных данных, который является реляционной базой данных в ссылочной реализации. Следующий фрагмент кода от FilteredRowSetSample
устанавливает свойства, необходимые, чтобы соединиться с базой данных, чтобы выполнить ее команду. Отметьте, что этот код использует DriverManager
class, чтобы сделать соединение, которое делается для удобства. Обычно, лучше использовать a DataSource
объект, который был зарегистрирован в службе именования, которая реализует Интерфейс Именования и Каталога Java (JNDI):
frs.setCommand("SELECT * FROM COFFEE_HOUSES"); frs.setUsername(settings.userName); frs.setPassword(settings.password); frs.setUrl(settings.urlString);
Следующая строка кода заполняет frs
objectwith данные, хранившие в COFFEE_HOUSE
таблица:
frs.execute();
Метод execute
делает все виды вещей в фоновом режиме, обращаясь RowSetReader
объект для frs
, то, который создает соединение, выполняет команду для frs
, заполняет frs
с данными от ResultSet
объект, который производится, и закрывает соединение. Отметьте это если таблица COFFEE_HOUSES
имел больше строк чем frs
объект мог содержать в памяти когда-то, CachedRowSet
методы оповещения использовались бы.
В сценарии владелец Перерыва на кофе сделал бы предыдущие задачи в офисе и затем импортировал бы или загрузил бы информацию, хранившую в frs
возразите против приложения сравнения кофейни. С этого времени, frs
объект будет работать независимо без преимущества соединения с источником данных.
Теперь, когда FilteredRowSet
объект frs
содержит список установлений Перерыва на кофе, можно установить критерии отбора для того, чтобы сузить число строк в frs
объект, которые видимы.
Следующая строка кода использует StateFilter
class, определенный ранее, чтобы создать объект myStateFilter
, который проверяет столбец STORE_ID
определить, какие хранилища находятся в Калифорнии (хранилище находится в Калифорнии, если ее Идентификационный номер между 10000 и 10999, включительно):
StateFilter myStateFilter = new StateFilter(10000, 10999, 1);
Следующие наборы строки myStateFilter
как фильтр для frs
.
frs.setFilter(myStateFilter);
Чтобы сделать фактическую фильтрацию, Вы вызываете метод next
, который в ссылочной реализации вызывает соответствующую версию Predicate.evaluate
метод, который Вы реализовали ранее.
Если возвращаемое значение true
, строка будет видима; если возвращаемое значение false
, строка не будет видима.
Вы устанавливаете многократные фильтры последовательно. В первый раз Вы вызываете метод setFilter
и передайте это a Predicate
объект, Вы применили критерии фильтрации в том фильтре. После вызова метода next
на каждой строке, которая делает видимым только те строки, которые удовлетворяют фильтр, можно вызвать setFilter
снова, передавая это различное Predicate
объект. Даже при том, что только один фильтр устанавливается за один раз, эффект состоит в том, что оба фильтра применяются кумулятивно.
Например, владелец получил список хранилищ Перерыва на кофе в Калифорнии, устанавливая stateFilter
как Predicate
объект для frs
. Теперь владелец хочет сравнить хранилища в двух Калифорнийских городах, Сан-Франциско (SF в таблице COFFEE_HOUSES
) и Лос-Анджелес (LA в таблице). Первое, что нужно сделать состоит в том, чтобы записать a Predicate
реализация, которая фильтрует для хранилищ или в SF или в LA:
public class CityFilter implements Predicate { private String[] cities; private String colName = null; private int colNumber = -1; public CityFilter(String[] citiesArg, String colNameArg) { this.cities = citiesArg; this.colNumber = -1; this.colName = colNameArg; } public CityFilter(String[] citiesArg, int colNumberArg) { this.cities = citiesArg; this.colNumber = colNumberArg; this.colName = null; } public boolean evaluate Object valueArg, String colNameArg) { if (colNameArg.equalsIgnoreCase(this.colName)) { for (int i = 0; i < this.cities.length; i++) { if (this.cities[i].equalsIgnoreCase((String)valueArg)) { return true; } } } return false; } public boolean evaluate(Object valueArg, int colNumberArg) { if (colNumberArg == this.colNumber) { for (int i = 0; i < this.cities.length; i++) { if (this.cities[i].equalsIgnoreCase((String)valueArg)) { return true; } } } return false; } public boolean evaluate(RowSet rs) { if (rs == null) return false; try { for (int i = 0; i < this.cities.length; i++) { String cityName = null; if (this.colNumber > 0) { cityName = (String)rs.getObject(this.colNumber); } else if (this.colName != null) { cityName = (String)rs.getObject(this.colName); } else { return false; } if (cityName.equalsIgnoreCase(cities[i])) { return true; } } } catch (SQLException e) { return false; } return false; } }
Следующий фрагмент кода от FilteredRowSetSample
устанавливает новый фильтр и выполняет итерации через строки в frs
, распечатывание строк, где CITY
столбец содержит или SF или ЛА. Отметьте это frs
в настоящий момент содержит только строки, где хранилище находится в Калифорнии, таким образом, критерии Predicate
объект state
все еще в действительности, когда фильтр изменяется на другого Predicate
объект. Код, который следует, устанавливает фильтр к CityFilter
объект city
. CityFilter
реализация использует массивы в качестве параметров конструкторам, чтобы иллюстрировать, как это может быть сделано:
public void testFilteredRowSet() { FilteredRowSet frs = null; StateFilter myStateFilter = new StateFilter(10000, 10999, 1); String[] cityArray = { "SF", "LA" }; CityFilter myCityFilter = new CityFilter(cityArray, 2); try { frs = new FilteredRowSetImpl(); frs.setCommand("SELECT * FROM COFFEE_HOUSES"); frs.setUsername(settings.userName); frs.setPassword(settings.password); frs.setUrl(settings.urlString); frs.execute(); System.out.println("\nBefore filter:"); FilteredRowSetSample.viewTable(this.con); System.out.println("\nSetting state filter:"); frs.beforeFirst(); frs.setFilter(myStateFilter); this.viewFilteredRowSet(frs); System.out.println("\nSetting city filter:"); frs.beforeFirst(); frs.setFilter(myCityFilter); this.viewFilteredRowSet(frs); } catch (SQLException e) { JDBCTutorialUtilities.printSQLException(e); } }
Вывод должен содержать строку для каждого хранилища, которое находится в Сан-Франциско, Калифорнии или Лос-Анджелесе, Калифорния. Если была строка в который CITY
столбец содержавший LA и STORE_ID
столбец, содержавший 40003, это не было бы включено в список, потому что это было уже отфильтровано, когда фильтр был установлен к state
. (40003 не находится в диапазоне 10000 - 10999.)
Можно произвести изменение в a FilteredRowSet
возразите, но только если то изменение не нарушает ни одного из критериев фильтрации в настоящий момент в действительности. Например, можно вставить новую строку или изменить одно или более значений в существующей строке, если новое значение или значения в пределах критериев фильтрации.
Предположите, что две новых кофейни Перерыва на кофе только что открылись, и владелец хочет добавить их к списку всех кофеен. Если строка, которая будет вставлена, не будет соответствовать совокупным критериям фильтрации в действительности, то она будет блокирована от того, чтобы быть добавленным.
Текущее состояние frs
объект состоит в том что StateFilter
объект был установлен и затем CityFilter
объект был установлен. В результате frs
в настоящий момент делает видимым только те строки, которые удовлетворяют критерии для обоих фильтров. И, одинаково важный, невозможно добавить строку к frs
возразите, если это не удовлетворяет критерии для обоих фильтров. Следующий фрагмент кода пытается вставить две новых строки в frs
объект тот, одна строка, в который значения в STORE_ID
и CITY
столбцы и соответствуют критериям, и одной строке в который значение в STORE_ID
не передает фильтр, но значение в CITY
столбец делает:
frs.moveToInsertRow(); frs.updateInt("STORE_ID", 10101); frs.updateString("CITY", "SF"); frs.updateLong("COF_SALES", 0); frs.updateLong("MERCH_SALES", 0); frs.updateLong("TOTAL_SALES", 0); frs.insertRow(); frs.updateInt("STORE_ID", 33101); frs.updateString("CITY", "SF"); frs.updateLong("COF_SALES", 0); frs.updateLong("MERCH_SALES", 0); frs.updateLong("TOTAL_SALES", 0); frs.insertRow(); frs.moveToCurrentRow();
Если Вы должны были выполнить итерации через frs
объект используя метод next
, Вы нашли бы строку для новой кофейни в Сан-Франциско, Калифорния, но не для хранилища в Сан-Франциско, Вашингтоне.
Владелец может добавить хранилище в Вашингтоне, аннулируя фильтр. Без набора фильтра, всех строк в frs
объект еще раз видим, и хранилище в любом расположении может быть добавлено к списку хранилищ. Следующая строка кода сбрасывает текущий фильтр, эффективно аннулируя оба из Predicate
реализации, ранее установленные на frs
объект.
frs.setFilter(null);
Если владелец решит закрыться или продать одну из кофеен Перерыва на кофе, то владелец будет хотеть удалить ее из COFFEE_HOUSES
таблица. Владелец может удалить строку для неблагополучной кофейни, пока строка видима.
Например, учитывая, что метод setFilter
был только что вызван с нулем параметра, нет никакого набора фильтра на frs
объект. Это означает, что все строки видимы и могут поэтому быть удалены. Однако, после StateFilter
объект myStateFilter
был установлен, который отфильтровывал любое состояние кроме Калифорнии, только хранилища, расположенные в Калифорнии, могли быть удалены. Когда CityFilter
объект myCityFilter
был установлен для frs
объект, только кофейни в Сан-Франциско, Калифорнии или Лос-Анджелесе, Калифорния могла быть удалена, потому что они были в единственных видимых строках.