Модераторы: LSD, AntonSaburov

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> генератор(?) SQL-запросов 
:(
    Опции темы
chinook
Дата 20.5.2005, 19:33 (ссылка)    |    (голосов: 0) Загрузка ... Загрузка ... Быстрая цитата Цитата


Unregistered











Привет!

Есть приложение, которое получает данные из базы. Вариантов запросов много, запросы сложные. Код - отстой. Конструирование запросов разбросано по сотне классов, каждый сам для себя.

Грядет переписывание этой кучи мусора, поэтому я хотел бы локализовать создание query в одном месте. Для меня очевидно (:-)), что такой объект = composit + interpreter, мы в произвольном порядке загоняем туда условия, потом получаем строку, представляющую из себя query. Я, собственно, уже продумал структуру и все такое.

Но!

Во-первых, не хочется изобретать велосипед, возможно, все до меня уже сделали.

Во-вторых, возможно, это не самый лучший путь, и кто-то знает лучший.

Собственно, вопросы: кто-нибудь про такой подход слышал? кто-нибудь с такой проблеммой сталкивался?

Заранее благодарен!

  Вверх
Stampede
Дата 20.5.2005, 20:28 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Гносеолог
**


Профиль
Группа: Участник Клуба
Сообщений: 963
Регистрация: 25.4.2005
Где: Calgary, Alberta, Canada

Репутация: 66
Всего: 144



Цитата(chinook @ 20.5.2005, 19:33)
Собственно, вопросы: кто-нибудь про такой подход слышал? кто-нибудь с такой проблеммой сталкивался?


Слышать не слышать, но сталкиваться - сталкивался. И более того, реализовывал.

Разумеется, задача не совсем тривиальная, и с наскоку ее не решишь. Я. в частности, поступил следующим образом. Я создал фреймворк из абстрактных понятий:
  • Attribute
  • Value
  • Query
  • Expression

Описатели аттрибутов не зашиты в код и хранятся отдельно (в базе, в XML, в проперях - неважно). Описатель содержит такие сведения: имя таблицы/столбца, тип данных, имя атрибута и плюс еще всякие флаги.

Value - это иерархия типизированных описателей значений, которые знают, как представлять себя в базе и на экране.

Expression - это собственно условие поиска, которое подразделяется на логические условия и атомарные условия. Таким образом можно строить запросы неограниченной вложенности.

Query - это надстройка над Expression, которая может включать дополнительную информацию о порядке сортировки, диапазоне поиска и пр.

Важный момент: в этих интерфейсах нет ни намека на SQL, потому что клиенту об этом знать совершенно необязательно. На сервере эти интерфейсы расширены до SqlExpression и SqlQuery, соответственно, и у них есть методы, специфические для пострения собственно выражений SQL.

Вот в общих словах и весь подход. У меня - работает.

Да, там есть еще один интересный момент, связанный с поддержкой разных типов СУБД. Там фишка в том, что выносить конструкции SQL в ресурсы очень неудобно, потому что при написании/отладке хорошо видеть, что именно у тебя происходит. Поэтому тексты шаблонов у меня зашиты прямо в сорцах. А чтобы иметь возможность менять синтаксис в зависимости от СУБД, я создал базовый класс Flavored, и все прочие классы, которые содержат код SQL, унаследованы от него.

У этого класса есть два метода , setFlavor(String flavor) и getFlavored(String str). Первый используется при инициализации класса, чтобы установить версию, например, "postgres". А вот когда приходит время собственно генерировать запрос, то используется примерно такой код:

Код

private static String sortClause = "order by $1 $2";
private static String sortClausePostgres = "order by lower($1) $2 ";
private String getSortClause()
// допустим, в постгресе порядок сортировки по умолчанию чувствителен к регистру, а мы хотим сделать наоборот

{
...
  String template = getFlavored(sortClause);
...
}



А внутри происходит следующее: когда вызывается getFlavored(), он использует рефлексию и ищет имя переменной, которая соотвествует переданной строке. В данном случае это переменная sortClause. После этого он присоединяет к имени переменной ранее установленный тип базы (postgres) и ищет переменную sortClausePostgres. Если таковая находится, он возвращает ее значение, если нет - то возвращает исходную строку.

Метод довольно зыбкий, потому что тут получается очень жесткий контракт, который по незнанию или забывчивости легко нарушить, и никто на этапе компиляции даже не пикнет, но если его придерживаться, то получается весьма удобно.

ЗЫ. А ты чего до сих пор не зарегистрируешься? Шестым чувством чувствую, что мы с тобой земляки smile

PM WWW   Вверх
Chinook
Дата 21.5.2005, 01:51 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 8
Регистрация: 21.5.2005
Где: Vancouver, BC, Ca nada

Репутация: нет
Всего: нет



Спасибо за подробный ответ!

Круто и все такое! У нас планируется нечто типа того, но это у нас называется metadata. Дело в том, что в зависимости от выбора основного источника данных, связанные данные могут находится в совершенно различных таблицах с различной структурой. В результате, после обращения к классам, работающих с metadata, мы получаем таблицы и список полей, по которым они связаны.

А вот дальше надо составить собственно запрос. Пока это решается компонованием строки в зависимости от условий (таблиц, подзапросов, полей для связывания и т.п.).

Я не собиралься замахиваться на такого монстра, как у тебя :-) Забумывалось написать класс, не привязанный к определенной структуре данных, который может принимать:
1. Поля для select
2. таблицы для from
3. поля для where с условием связывания (=, *=, >...) и условием обязательности (or and)
4. поля для having
5. поля для order by

При этом 1, 2, 3 могут быть тем же классом (т.е. вложенные подзапросы - у нас Oracle, который это понимает).

Преимущества такого подхода:
1. все построение запросов в одном месте
2. нет определенного порядка добавления элементов (а то в полупостроенном запросе приходится вставлять новый подзапрос в группу from - выглядит ужасно)
3. Код бизнес-классов не захламляется всякими строками с кусками запроса (ну, это производное).
4. этот класс (скорее - пакет) можно будет использовать к любом приложении (по крайней мере с ораклом)

Почему, собственно, кажется это целесообразным:
1. interpter: шаблон для перевода чего-либо с одного языка на другой. Т.е. перевод на sql - сам Бог велел.
2. composit: обход дерева, в которое превращается запрос - все точно по документации.

Просто посроение такого класса(пакета) мне кажется очевидным, если начинать что-то новое, заранее зная про большое количество разнородных запросов. Поэтому я и спросил - неверняка такой пакет уже написан, и, учитывая большое количество исходников в и-нете, мог попасться кому-то на глаза(на мои не попался).

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


Цитата
ЗЫ. А ты чего до сих пор не зарегистрируешься? Шестым чувством чувствую, что мы с тобой земляки

Зарегистрировался. Шестым!?!?! Ну, возможно :-) Я вообще-то из Воронежа, живу в Ванкувере.





Добавлено @ 01:54
О, блин, Калгари! А я что-то затормозил :-) Ну да, точно, чинук - это, слава Богу, у вас :-)

PM MAIL   Вверх
tux
Дата 21.5.2005, 04:05 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Летатель
***


Профиль
Группа: Участник Клуба
Сообщений: 1853
Регистрация: 10.2.2005
Где: msk.ru

Репутация: 74
Всего: 132



Может быть еще вот эта статья Скотта Эмблера (из Торонто!!! smile ) поможет - http://www.ambysoft.com/persistenceLayer.pdf. Она посвящена архитектуре библиотеки объектно-реляционного отображения, но идеи похожи.
PM MAIL Skype GTalk Jabber YIM   Вверх
batigoal
Дата 21.5.2005, 11:20 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Нелетучий Мыш
****


Профиль
Группа: Участник Клуба
Сообщений: 6423
Регистрация: 28.12.2004
Где: Санктъ-Петербургъ

Репутация: 16
Всего: 151



tux
Спасибо за линк. Обязательно прочту.


--------------------
"Чтобы правильно задать вопрос, нужно знать большую часть ответа" (Р. Шекли)
ЖоржЖЖ
PM WWW   Вверх
maximb
Дата 23.5.2005, 10:31 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Awaiting Authorisation
Сообщений: 48
Регистрация: 23.5.2005
Где: Украина, г.Симфер ополь

Репутация: 2
Всего: 6



А может стоит использовать Hibernate
Зачем изобретать велосипед
PM ICQ   Вверх
batigoal
Дата 23.5.2005, 10:42 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Нелетучий Мыш
****


Профиль
Группа: Участник Клуба
Сообщений: 6423
Регистрация: 28.12.2004
Где: Санктъ-Петербургъ

Репутация: 16
Всего: 151



Может, и стоит, просто я его пока не знаю smile


--------------------
"Чтобы правильно задать вопрос, нужно знать большую часть ответа" (Р. Шекли)
ЖоржЖЖ
PM WWW   Вверх
maximb
Дата 23.5.2005, 10:49 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Awaiting Authorisation
Сообщений: 48
Регистрация: 23.5.2005
Где: Украина, г.Симфер ополь

Репутация: 2
Всего: 6



Да там не так сложно, главное научиться нормально писать маппинги на классы и все.

Да и еще, небольшое дополнение:
Для обеспечения нормальных транзакций и упрощения работы с транзакциями
очень хорошо использовать Spring в одной связке с Hibernate.
PM ICQ   Вверх
tux
Дата 23.5.2005, 10:53 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Летатель
***


Профиль
Группа: Участник Клуба
Сообщений: 1853
Регистрация: 10.2.2005
Где: msk.ru

Репутация: 74
Всего: 132



В данном случае это приведет к необходимости создания слоя хранимых объектов и преобразования запросов из SQL в объектные запросы на HQL. Не уверен, что преобразование всегда можно будет выполнить один в один. В частности это зависит от того, в каком объеме используются функции, характерные только для данной используемой СУБД. Хотя генератор запросов на HQL в Hibernate уже есть и если запросы не очень сложные и их не очень много возможно что действительно использование Hibernate оправдано.
PM MAIL Skype GTalk Jabber YIM   Вверх
maximb
Дата 23.5.2005, 10:58 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Awaiting Authorisation
Сообщений: 48
Регистрация: 23.5.2005
Где: Украина, г.Симфер ополь

Репутация: 2
Всего: 6



Если очень надо могу помочь примером "Spring + Hibernate"
Но придется денек подождать т.к. мне его надо будет сделать.

То, что у меня уже есть к сожалению дать не могу т.к. это текущий проект.
Добавлено @ 11:07
Цитата(tux @ 23.5.2005, 10:53)
В данном случае это приведет к необходимости создания слоя хранимых объектов и преобразования запросов из SQL в объектные запросы на HQL. Не уверен, что преобразование всегда можно будет выполнить один в один. В частности это зависит от того, в каком объеме используются функции, характерные только для данной используемой СУБД. Хотя генератор запросов на HQL в Hibernate уже есть и если запросы не очень сложные и их не очень много возможно что действительно использование Hibernate оправдано.

Да но это избавляет программиста от того, чтобы делать преобразования запросов для разных БД вручную, вся ответственность ложится на Hibernate.
Насчет сложности запросов, то средствами Hibernate можно делать запросы любой сложности.

PM ICQ   Вверх
Domestic Cat
Дата 23.5.2005, 11:10 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Экс. модератор
Сообщений: 5452
Регистрация: 3.5.2004
Где: Dallas, US

Репутация: 13
Всего: 172



Цитата
Где: Vancouver, BC, Canada


smile smile Канадская диаспора на русском форуме

smile Сори за офтоп


--------------------

PM   Вверх
maximb
Дата 23.5.2005, 11:15 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Awaiting Authorisation
Сообщений: 48
Регистрация: 23.5.2005
Где: Украина, г.Симфер ополь

Репутация: 2
Всего: 6



Domestic Cat smile)



Сорри, сразу не увидел но обсуждение Hibernate
ведется еще и в этом топике
http://forum.vingrad.ru/index.php?showtopic=31813
PM ICQ   Вверх
3,14
Дата 23.5.2005, 11:18 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Участник Клуба
Сообщений: 1614
Регистрация: 18.6.2004
Где: Н. Новгород

Репутация: 3
Всего: 24



ИМХО использовать Hibernate и если есть возможность все запросы вынести на сторону БД


--------------------
Может быть, это только мой бред,
Может быть, жизнь не так хороша,
Может быть, я не выйду на свет,
Но я летал, когда пела душа...
PM MAIL   Вверх
tux
Дата 23.5.2005, 11:28 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Летатель
***


Профиль
Группа: Участник Клуба
Сообщений: 1853
Регистрация: 10.2.2005
Где: msk.ru

Репутация: 74
Всего: 132



Цитата
Насчет сложности запросов, то средствами Hibernate можно делать запросы любой сложности.

Язык запросов, сглаживающий различия между различными СУБД, по определению должен обладать меньшими возможностями, чем язык запросов СУБД. Хотя, не спорю, в подавляющем большинстве случаев его вполне достаточно.
PM MAIL Skype GTalk Jabber YIM   Вверх
maximb
Дата 23.5.2005, 11:37 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Awaiting Authorisation
Сообщений: 48
Регистрация: 23.5.2005
Где: Украина, г.Симфер ополь

Репутация: 2
Всего: 6



Цитата(tux @ 23.5.2005, 11:28)
Язык запросов, сглаживающий различия между различными СУБД, по определению должен обладать меньшими возможностями, чем язык запросов СУБД. Хотя, не спорю, в подавляющем большинстве случаев его вполне достаточно.

За универсальность надо платить smile

Понятно, что собственная реализация работы с БД (если все правильно сделано)
может быть лучше чем универсальный подход, но в этом случае не надо забывать сколько времени и сил уйдет на эту собственную реализацию.
+ Суппорт, стоит внести небольшие изменения в модель данных или перейти на другую БД
как придется переписывать массу запросов, что в Хибернейте решается простым переписыванием маппингов (и то это придется делать только в том случае если произошли изменения в модели)
PM ICQ   Вверх
Ответ в темуСоздание новой темы Создание опроса
Правила форума "Java"
LSD   AntonSaburov
powerOn   tux
  • Прежде, чем задать вопрос, прочтите это!
  • Книги по Java собираются здесь.
  • Документация и ресурсы по Java находятся здесь.
  • Используйте теги [code=java][/code] для подсветки кода. Используйтe чекбокс "транслит", если у Вас нет русских шрифтов.
  • Помечайте свой вопрос как решённый, если на него получен ответ. Ссылка "Пометить как решённый" находится над первым постом.
  • Действия модераторов можно обсудить здесь.
  • FAQ раздела лежит здесь.

Если Вам помогли, и атмосфера форума Вам понравилась, то заходите к нам чаще! С уважением, LSD, AntonSaburov, powerOn, tux.

 
1 Пользователей читают эту тему (1 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Java EE (J2EE) и Spring | Следующая тема »


 




[ Время генерации скрипта: 0.1170 ]   [ Использовано запросов: 21 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.