Достаточно часто перед разработчиком стоит задача по сортировке коллекций. Это может быть список клиентов в алфавитном порядке или прайс-лист продукции, упорядоченный по цене. В этой статье рассмотрим варианты сортировки, которые предлагает фреймворк FBA Toolkit, а также покажем, как можно реализовать свой вариант упорядочивания.
Сортировка записей запроса
Пожалуй, самым оптимальным по производительности вариантом будет выполнение сортировки непосредственно при выборке данных из базы, используя SQL-синтаксис.
а) Менеджеры данных (классы RowDao и его наследники) реализуют функции select и selectCursor в которые дополнительным параметром могут быт переданы условия сортировки:
1 2 3 4 5 6 7 8 9 10 11 12 | /* * Выбрать все записи из справочника (не установлен отбор первым параметром) * отсортированные по наименованию */ return dao.select(null, CatalogNomenklatura.FIELD_NAME_DESCRIPTION); /* * Отбор по родителю, сортировка – группы сверху */ return dao.select(parent, null, null, CatalogNomenklatura.FIELD_NAME_LEVEL + ", " + CatalogNomenklatura.FIELD_NAME_FOLDER + " DESC"); |
/* * Выбрать все записи из справочника (не установлен отбор первым параметром) * отсортированные по наименованию */ return dao.select(null, CatalogNomenklatura.FIELD_NAME_DESCRIPTION); /* * Отбор по родителю, сортировка – группы сверху */ return dao.select(parent, null, null, CatalogNomenklatura.FIELD_NAME_LEVEL + ", " + CatalogNomenklatura.FIELD_NAME_FOLDER + " DESC");
б) Так же вы можете использовать построитель запроса OrmLite:
1 2 3 4 5 6 7 8 9 10 11 12 13 | public class CatalogNomenklaturaDao extends CatalogDao<CatalogNomenklatura> { /* * Пример указания сортировки с помощью построителя запроса OrmLite: * помеченные на удаление элементы будут внизу списка */ public List<CatalogNomenklatura> selectBuilderRaw() throws SQLException { QueryBuilder<CatalogNomenklatura, String> builder = queryBuilder(); builder.orderByRaw(CatalogNomenklatura.FIELD_NAME_DELETIONMARK + " DESC"); return query(builder.prepare()); } } |
public class CatalogNomenklaturaDao extends CatalogDao<CatalogNomenklatura> { /* * Пример указания сортировки с помощью построителя запроса OrmLite: * помеченные на удаление элементы будут внизу списка */ public List<CatalogNomenklatura> selectBuilderRaw() throws SQLException { QueryBuilder<CatalogNomenklatura, String> builder = queryBuilder(); builder.orderByRaw(CatalogNomenklatura.FIELD_NAME_DELETIONMARK + " DESC"); return query(builder.prepare()); } }
в) и ручное составлением инструкций SQL на выборку данных с указанием сортировки. Этот вариант самый гибкий, но и самый сложный при этом.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 | public List<CatalogNomenklatura> selectRaw() throws SQLException { //Составление текста запроса: выборка только необходимых полей и указание сортировки StringBuilder sb = new StringBuilder(); sb.append(" SELECT ") .append(CatalogNomenklatura.FIELD_NAME_REF).append(",") .append(CatalogNomenklatura.FIELD_NAME_CODE).append(",") .append(CatalogNomenklatura.FIELD_NAME_DESCRIPTION); sb.append(" FROM ").append(CatalogNomenklatura.TABLE_NAME); sb.append(" ORDER BY ") .append(CatalogNomenklatura.FIELD_NAME_DESCRIPTION + " DESC"); //Выборка данных с преобразованием результата к коллекции объектов GenericRawResults<CatalogNomenklatura> rawResults = queryRaw( sb.toString(), new RawRowMapper<CatalogNomenklatura>() { @Override public CatalogNomenklatura mapRow(String[] columnNames, String[] resultColumns) throws SQLException { CatalogNomenklatura item = new CatalogNomenklatura(); item.setRef(UUID.fromString(resultColumns[0])); item.setCode(resultColumns[1]); item.setDescription(resultColumns[2]); return item; } }); //результат выборки как список return rawResults.getResults(); } |
public List<CatalogNomenklatura> selectRaw() throws SQLException { //Составление текста запроса: выборка только необходимых полей и указание сортировки StringBuilder sb = new StringBuilder(); sb.append(" SELECT ") .append(CatalogNomenklatura.FIELD_NAME_REF).append(",") .append(CatalogNomenklatura.FIELD_NAME_CODE).append(",") .append(CatalogNomenklatura.FIELD_NAME_DESCRIPTION); sb.append(" FROM ").append(CatalogNomenklatura.TABLE_NAME); sb.append(" ORDER BY ") .append(CatalogNomenklatura.FIELD_NAME_DESCRIPTION + " DESC"); //Выборка данных с преобразованием результата к коллекции объектов GenericRawResults<CatalogNomenklatura> rawResults = queryRaw( sb.toString(), new RawRowMapper<CatalogNomenklatura>() { @Override public CatalogNomenklatura mapRow(String[] columnNames, String[] resultColumns) throws SQLException { CatalogNomenklatura item = new CatalogNomenklatura(); item.setRef(UUID.fromString(resultColumns[0])); item.setCode(resultColumns[1]); item.setDescription(resultColumns[2]); return item; } }); //результат выборки как список return rawResults.getResults(); }
Сортировка списков объектов
Этот вариант сортировки может быть использован, кода данные уже считаны из базы и хранятся в коллекции List. Естественно этот вариант не применим для курсоров (selectCursor).
а) Начиная с версии 1.0.4, FBA Toolkit содержит встроенные методы сортировки:
- справочников по представлению;
- документов по дате
Теперь вы можете отсортировать коллекцию в одну строчку:
1 | Collections.sort(<ваш список>); |
Collections.sort(<ваш список>);
Например, сортировка справочника по представлению:
1 2 | List<CatalogNomenklatura> lst = <выборка из базы>; Collections.sort(lst); |
List<CatalogNomenklatura> lst = <выборка из базы>; Collections.sort(lst);
Направление сортировки будет зависеть от реализации метода getPresentation данного справочника:
1 2 3 4 5 6 7 | public class CatalogNomenklatura extends Catalog { @Override public String getPresentation() { return getCode(); } } |
public class CatalogNomenklatura extends Catalog { @Override public String getPresentation() { return getCode(); } }
Например, если основное представление элементов справочника в виде кода, то и сортировка будет по коду.
б) и наконец, вы можете создать свои правила сортировки с помощью интерфейса Comparatoг, например так:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 | public class ExTableCeniDao extends TableExDao<ExTableCeni> { /** * Возвращает прайс-лист отсортированный по цене и представлению номенклатуры * @param type тип цены * @return * @throws SQLException */ public List<ExTableCeni> getPriceOfType(CatalogTipiCenNomenklaturi type) throws SQLException{ HashMap<String,Object> filter = new HashMap<String, Object>(); filter.put(ExTableCeni.FIELD_NAME_TIP_CEN, type); List<ExTableCeni> data = select(filter); Collections.sort(data, sortedByPrice); return data; } /* * Сортировка по цене и представлению номенклатуры */ private Comparator<ExTableCeni> sortedByPrice = new Comparator<ExTableCeni>() { @Override public int compare(ExTableCeni lhs, ExTableCeni rhs) { if (lhs.cena > rhs.cena) return 1; else if (lhs.cena < rhs.cena) return -1; else if (CatalogNomenklatura.isEmpty(lhs.nomenklatura)) return -1; else return lhs.nomenklatura.compareTo(rhs.nomenklatura); } }; } |
public class ExTableCeniDao extends TableExDao<ExTableCeni> { /** * Возвращает прайс-лист отсортированный по цене и представлению номенклатуры * @param type тип цены * @return * @throws SQLException */ public List<ExTableCeni> getPriceOfType(CatalogTipiCenNomenklaturi type) throws SQLException{ HashMap<String,Object> filter = new HashMap<String, Object>(); filter.put(ExTableCeni.FIELD_NAME_TIP_CEN, type); List<ExTableCeni> data = select(filter); Collections.sort(data, sortedByPrice); return data; } /* * Сортировка по цене и представлению номенклатуры */ private Comparator<ExTableCeni> sortedByPrice = new Comparator<ExTableCeni>() { @Override public int compare(ExTableCeni lhs, ExTableCeni rhs) { if (lhs.cena > rhs.cena) return 1; else if (lhs.cena < rhs.cena) return -1; else if (CatalogNomenklatura.isEmpty(lhs.nomenklatura)) return -1; else return lhs.nomenklatura.compareTo(rhs.nomenklatura); } }; }
Метод getPriceOfType DAO-менеджера для внешней таблицы «Цены» возвращает коллекцию отсортированную по цене. Если цена одинаковая, сортировка выполняется по представлению номенклатуры. Результат сортировки:
Полностью исходный код по этой статье смотрите в примере “Заказ покупателя” в SVN-репоритории https://xp-dev.com/svn/fba_toolkit_public/samples/fbaSample3Order/. Переключитесь на соответствующую ревизию (ориентируйтесь по комментарию).
Если у вас есть вопросы или комментарии, используйте форму «Контакты» для связи.