Реальный пиарJavaScriptПишем на JavaScript → Проблемы реализации постраничной загрузки таблиц с помощью компонент Hibernate и Java

Проблемы реализации постраничной загрузки таблиц с помощью компонент Hibernate и Java

java приложения

При разработке корпоративных приложений одним из сложных вопросов, является реализация возможности обеспечения работы на клиентской части с большими объемами информации. Суть проблемы заключается в том - в каком виде и каким образом осуществлять отображение на терминалах клиента необходимой информации, c возможностью выполнять основные операции с массивами данных, в первую очередь это перемещение по ним в любом направлении, а также стандартные операции редактирования. С похожим решением данной проблемы сталкивался любой пользователь, осуществлявший хотя бы раз поиск во всемирной сети. Когда при вводе критерия поиска на экране отображается только часть искомых данных, а остальные разбиваются на страницы, номера которых выводятся в этом же окне в виде ссылок, с помощью которых можно перемещаться по результирующей выборке. Данный механизм – называется пагинацией (от англ. pagination) [1] и заключается в определении общего количества соответствующих критерию поиска ссылок, разбиение их на страницы и загрузка страниц по запросам пользователей. Следует признать, что в силу специфики сетевого взаимодействия и характера выводимой информации, данный механизм в этом случае является оптимальным.

Однако при выводе большого объема табличной информации (несколько десятков тысяч записей и более) на терминал пользователя, описанный выше подход неприемлем по многим причинам. В первую очередь это связано с трудностями реализации навигационных перемещений, например, моментальный переход в конец выборки, или прокручивании (скроллинге) в любом направлении. Очевидно, что данный механизм реализован поставщиками драйверов JDBC с соответствующей СУБД, при клиент - серверном взаимодействии, для чего необходимо только определенным образом настроить драйвер, не задумываясь об этих настройках в клиентских компонентах библиотеки Swing реализующих отображение данных посредством JTable и JScrollPane. Что значительно упрощает разработку и настройку приложений.

Однако как показывает практика, на сегодняшний день, данная архитектура не является лучшим решением, так как накладывает множество ограничений, как на производительность функционирования системы в целом, так и на возможности смены платформы.

Более оптимальным вариантом архитектуры корпоративного приложения является - клиент – сервер приложений – СУБД. В ОАО "РОСТОВЭНЕРГО" в настоящий момент выполняется реинженеринг существующей корпоративной информационной системы, перевод ее на многослойную архитектуру с использованием самых передовых на сегодняшний день технологий Java. Кроме того, система должна функционировать в гетерогенной среде СУБД (MS SQL Server, HSSQLDB, MySQL), а так же в силу специфики решаемых задач должна иметь и Web-интерфейс, и "толстого" клиента.

Целью данной статьи является рассмотрение способа реализации механизма пагинации при взаимодействии Swing-клиент – Hibernate – СУБД и анализ производительности системы (профайлинг) и способы ее повышения при его использовании.

Работа с объектно-ориентированным программным обеспечением и реляционной базой сопряжена с рядом трудностей. Hibernate - инструмент объектно/реляционного отображения данных (object/relational mapping tool = ORM tool) для Java окружения [2, 3, 4]. Термин объектно-реляционное отображение (object-relational mapping = ORM), относится к технике отображения объектно-ориентированных данных в реляционную модель со схемой данных основанной на SQL.

Hibernate не только заботится об отображении объектов Java классов в таблицы базы данных (и типов данных Java в типы данных SQL), но также обеспечивает механизм запроса и поиска данных, и значительно сокращает время разработки программного продукта, потраченное, в противном случае, на ручную обработку данных в SQL и JDBC.

Целью Hibernate является освобождение разработчика от 95 процентов общих работ, связанных с задачами программирования долгоживущих (persistence) данных. Возможно, Hibernate является наиболее полезным при использовании объектно-ориентированных моделей предметной области и бизнес логики в основанном на Java промежуточном слое (middle-tier). Hibernate помогает удалить из приложения или инкапсулировать (скрыть), зависящий от поставщика SQL-код и также помогает в решении стандартной задачи преобразования набора данных (result set) из табличного представления в объектный граф.

Поэтому необходимо использовать возможности библиотеки Hibernate для реализации механизма пагинации не зависящего от типа поставщиков драйверов JDBC. Одним из базовых моментов Hibernate – является "ленивая" инициализация, которая заключается в том, что при запросе к базе в выборку загружаются не объекты, а ссылки на них, и только при обращении к конкретной ссылке происходит выгрузка запрошенного объекта клиенту. Кроме того, Hibernate имеет множество дополнительных возможностей, общая идея которых заключается в повышении производительности работы всей системы в целом за счет снятия нагрузки с СУБД при использовании многоуровневой архитектуры. Вместе с тем данная библиотека предоставляет возможность реализации запросов с помощью традиционного синтаксиса языка SQL или встроенного HSQL. Однако следует заметить, что слой приложения, отвечающий за доступ к СУБД, реализованный с помощью SQL запросов не обладает той гибкостью и мощью, которую можно реализовать, используя запросы – критерионы (Criteria) библиотеки Hibernate и механизмы Reflection и RTTI - Java. Критерионы позволяют реализовать запросы, используя объектный подход, получая коллекцию искомых бизнес – объектов, а так же реализуя все основные конструкции традиционного SQL – группировка, агрегация, объединение см Листинг1, 2.
Листинг 1. Метод использующий Critetia, RTTI, Reflection для загрузки бизнес объектов в табличную модель
/**
*Метод для заполнения табличной модели бизнес объектами
*@param tableModel модель таблицы которую нужно заполнить
*@param cls класс бизнес – объекта, которым нужно заполнить таблицу
*/
public void fillTable(ModelTableEntities tableModel, Class cls){
// выбираем все методы класса
Method [] allMethods = cls.getMethods();
//Method nesMethod = null;
List searchMethod = new ArrayList();
// перебор всех методов класса
for (int i = 0; i < allMethods.length; i++) {
// перебор все заголовков таблицы
for(int j=0;j < tableModel.getColumnArray().length; j++) {

// проверка маской на соответствие название метода заголовку столбца...
if(
allMethods[i].getName()
.equalsIgnoreCase("get"+tableModel.getColumnArray()[j])
) {
// если соответствует то заносим в список
searchMethod.add(allMethods[i]);
}
}
}

// далее получаем список элементов бизнес - сущности
//и заносим его в таблицу
try{
for (Object elem : this.getCollectionEntity(cls)) {
Vector rowV = new Vector();
//перебор заголовков столбцов
for(int k = 0 ; k < tableModel.getColumnArray().length ; k++) {
for (Method mtd : searchMethod) {
if(mtd.getName()
.equalsIgnoreCase("get"+tableModel.getColumnArray()[k])) {
// формируем строку
rowV.add(mtd.invoke(elem));
}
}
}
tableModel.addRow(rowV);
}
}catch(Exception nme){this.showErrorMessage(nme);}
}
Листинг 2. Фрагмент кода метода, использующего Criteria для реализации агрегирующих запросов
//Текстовый массив запроса
String [][] strPar = new String [parAnal.size()][2];
for (int i = 0; i < parAnal.size(); i++ ) {
Object [] tmpAnal = (Object[])parAnal.get(i);
strPar[i][0] = tmpAnal[0].toString();
strPar[i][1] = tmpAnal[1].toString();
}
// Массив параметров
String [] parQ = new String [(strPar.length+2)];
parQ[0] = "accountCredit";
Type [] typeQ = new Type[parQ.length];
typeQ[0] = Hibernate.LONG;
for (int i = 0; i < strPar.length; i++){
parQ[i+1] = strPar[i][0];
typeQ[i+1] = Hibernate.INTEGER;
}
parQ[(strPar.length+1)] = "summ";
typeQ[(strPar.length+1)] = Hibernate.BIG_DECIMAL;

String selectSQL = "";
String groupSQL = "";
String whereSQL = "";

for (int i = 0; i < (parQ.length - 1); i++) {
if(i == (parQ.length - 2))
groupSQL = selectSQL + parQ[i];
else
groupSQL = selectSQL + parQ[i]+", ";

selectSQL = selectSQL + parQ[i]+", ";
}
selectSQL = selectSQL +"sum(summ)as summ";

//Выбор с группировкой суммы проводок по кредитовым счетам

list = this.getSession().createCriteria(Entry.class)
.add(Restrictions.and(
Restrictions.eq("accountCredit", account),
Restrictions.and(
Restrictions.ge( "entryDate", beg),
Restrictions.lt( "entryDate", end)))
)
.setProjection(Projections.projectionList()
.add(Projections.sqlGroupProjection(selectSQL,
groupSQL,
parQ, typeQ))
)
.list();

Следует помнить, что данный подход дает преимущества только при больших объемах данных и распределенном характере приложения. В остальных случаях использование Hibernate не приведет к существенному повышению производительности, а скорее наоборот будет ее снижать.

Таким образом, для реализации пагинации необходимо, чтобы компонент библиотеки Hibernate имел методы для быстрого перемещения по выборке в любом направлении, позволял работать с большими объемами данных, при этом постараться свеcти к минимуму количество обращений к СУБД. В данном случае в качестве СУБД используется MySQL v.5, тестовая таблица состоит из 102 тысяч записей, размер таблицы 60 Мб. Были проанализированы возможные варианты решения. В частности, одним из способов является явное указание, в запросе границ выборки используя методы setFirstResult(int numRow) и q.setMaxResults(int numRow) для объекта Criteria, которым в качестве параметров передавать нужные строки. Однако такой вариант во–первых при листании будет постоянно генерировать запросы к СУБД, во – вторых невозможно установить общее количество бизнес – объектов, так как попытки загрузки всей коллекции вызывали переполнение памяти. Наиболее оптимальным компонентом является интерфейс ScrollableResults, который имеет все необходимые методы для перемещения по выборке, а использование класса DetachedCriteria, позволяет после выборки объектов закрыть сессию с СУБД


Источник: http://www.javaportal.ru

Рекомендуем



Регулярные выражения в Java (regexp) Эти операции осуществляются с помощью универсальных символов, которые специальным образом интерпретируются


Введение в превалирование объектов Разработчик должен преобразовать объекты в таблицы баз данных, XML файлы, или использовать какой-нибудь другой не объектно-ориентированный способ представления данных, полностью нарушающий инкапсуляцию


Использование Hibernate Java Persistence На практике наибольшую популярность получили именно реляционные модели баз данных, хотя в современных методологиях программирования пользуется популярностью объектно-ориентированное программирование