Какие запросы мешают вам использовать ORM?

atv

Новичок
master_x
ORM-- вещь полезная, хотя бы потому что делает код читабельным.
Может быть и полезная, но только не этим. Читабельность SQL, специально разработанного для обращения к структурам данных, вряд ли чем то переплюнеш.

whirlwind
Т.е. если ты ООП не используешь, как ты можешь судить плохо юзать ORM или хорошо?
Зачем же переходить на личности. Нужно оперировать аргументами. К WP это тоже относиться.
 

whirlwind

TDD infected, paranoid
atv при чем здесь личности? аргумент в данном случае - это использование ООП.

atv ты можешь сформулировать что такое ORM и с чем его едят. У меня такое ощущение, что для тебя ORM - это механизм вытаскивания данных из таблиц. Потому что только в такой формулировке ORM выглядит нелепой пятой ногой.
 

atv

Новичок
при чем здесь личности? аргумент в данном случае - это использование ООП.
без слов...

ты можешь сформулировать что такое ORM и с чем его едят.
Не могу. Не исключено, что я чего-то не понимаю, а из того что я понимаю сложилась точка зрения высказанная мною выше.

У меня такое ощущение, что для тебя ORM - это механизм вытаскивания данных из таблиц.
SQL позволяет четыре действия работы с данными. При каждом действии приходиться учитывать структуру данных. ORM, как я понимаю, призван облегчить работу с данными. Однако сложность возникает как раз с учётом структуры данных. В какой формулировке ORM будет выглядеть лучше?
 

whirlwind

TDD infected, paranoid
ORM не призван облегчить работу с данными. В первую очередь, ORM это способ продлить время существования объектов в соответствии с требованиями алгоритма, а не временем работы программы. Все это имеет значение только в тех программах, где объекты являются элементами бизнес логики. ORM реализует прозрачное извлечение связанных объектов. SQL тут вообще только в качестве средства реализации фигурирует. В качестве механизма продления жизни может быть выбрано все что угодно от Serialize и XML, до РСУБД. По этому я и говорю

>аргумент в данном случае - это использование ООП

Потому что если мыслишь функциями или таблицами (читай датасетами), а не активной моделью, то ORM не нужен.
 

atv

Новичок
В первую очередь, ORM это способ продлить время существования объектов...
Я думал это называется Persistent Object. А как же Object Relational Mapping, или название неточное. Похоже мы утонем в тонкостях формулировок и понятий. Поэтому пусть будет "Все просто - либо вы используете ORM, либо нет."

П.С. Вот кстати цитата "Выражаясь более простым языком, объектно-реляционный проектор - ОРП - позволяет программисту прозрачно работать с таблицами, полями и связями реляционной БД, как с объектами, свойствами и коллекциями (массивами)..." отсюда http://www.arbinada.com/modules.php?name=Content&pa=showpage&pid=82
 

whirlwind

TDD infected, paranoid
> Я думал это называется Persistent Object

А какой м.б. relation для не persistent? А во вторых, даже из той же статьи вы выбрали наиболее подходящее под ваше понимание цитату, а самое главное

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

PS. И вообще, с какой стати кратенькая статейка, в которой не рассматривается ни одной специфичной проблемы ORM, претендует на роль эталона и абсолютной истины?
 

dr-sm

Новичок
Да кстати, кроме полновесного ORM, сущеcтвуют более другие решения, например iBATIS Data Mapper, но он, к сожалению, только для java & .net вроде. Никто не видел что-нибуть подобного для PHP?
 

bkonst

.. хочется странного?...
atv
Объектам приложения также нужен именно срез, поэтому и возникают проблемы при маппинге. Т.е. маппинг, как таковой, и невозможен, только в тех случаях, когда реляционная модель несложная.
Почему? Реляционная модель - это просто способ хранить данные без избыточности, позволяющий обрабатывать их с хорошей скоростью. Маппинг объектной модели на реляционную и обратно можно делать по достаточно простым алгоритмам - так как практически любая объектная модель сводится к связям 1:N / N:M. Если я ошибаюсь - приведите пример, так как именно поэтому тема и была поднята.

Читабельность SQL, специально разработанного для обращения к структурам данных, вряд ли чем то переплюнеш.
Если структуры данных содержат связи N:M, запрос будет "засоряться" вспомогательными таблицами, например. При связи трех-четырех сущностей - условиями, по которым производится связывание. ORM позволяет скрыть это, используя информацию из описания модели. Чем не улучшение читабельности?

whirlwind
А это не имееет никакого отношения к ORM. При кривой структуре базы это будет непросто сделать и в виде одного запроса.
Опять-таки, насколько, с вашей точки зрения, востребованы такие запросы? И насколько существующие ORM позволяют их реализовывать, не опускаясь к уровню SQL (то есть, насколько востребована такая функциональность)? Лично мне не нравится идея реализации такой обработки на уровне бизнес-логики, так как результатом может стать огромнейшее количество мелких запросов к базе.

Обратите внимание, я не нападаю на ORM; я пытаюсь уточнить, есть ли нужда в расширении функциональности существующим библиотек (или существуют ли ORM с достаточным её уровнем).

WP
А вот генерировать статические запросы вселенский изврат. Во-первых это идеологически неверно, т.к. SQL не требует диалектов, для этого и создан. Ведь сами подумайте - бред, сначала создавать запрос, а потом его же парсить (СУБД).
Ну, мы же используем XML для обмена данными? Почему SQL должен рассматриваться иначе?

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

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

Велосипедом является как раз ORM, ведь оно оправдано лишь в некоторых случаях, когда речь идет об однотипной выборке по куче статических критериев без связи.
Почему? Выше вы сказали, что "а вот генерировать статические запросы вселенский изврат". Теперь получаем, что ORM оправдывает себя только для выборок по куче статических критерием - то есть только для того, что можно описать обычных параметризованным запросом.

Как с вашей точки зрения, чем обуславливается "неоправданность" применения ORM для более сложных выборок? Отсутствием функциональности? Неэффективной реализацией существующих ORM? Невозможностью отображения каких-то запросов на объектную модель?

master_x
никакие запросы не мешают, потому что где они сложные пишу их на SQL.
Хотелось бы иметь возможность реализовывать их на уровне ORM, или это всё-таки излишество?
 

Alexandre

PHPПенсионер
почему я не использую ОРМ?, простые запросы из жизни,
как это будет выглядеть в терминах ORM?
[sql]select distinct emhe_catalog_id, o.objects_id, o.rus_name, o.shortname , o.object_types_id, c.object_types_id from objects o, emhe_catalog_objects c where o.objects_id = c.objects_id
and o.object_types_id = 6 and emhe_catalog_id
IN (
select emhe_catalog_id from emhe_catalog where cleft > 173 AND cright < 186 and clevel=3
) ORDER BY emhe_catalog_id;
[/sql]
[sql]select c.shortname, o.objects_id , o.shortname , o.rus_name, v.rus_value, v.selects_vals_id
from emhe_catalog c
left join emhe_catalog_objects co on co.emhe_catalog_id = c.emhe_catalog_id
left join objects o on o.objects_id = co.objects_id
left join select_object_vals vo on vo.objects_id = o.objects_id
left join selects_vals v on vo.selects_vals_id = v.selects_vals_id
where c.shortname='2006clubs'
and v.selects_vals_id = 202
limit 20;[/sql]
[sql]SELECT
banner_id, goto, file, left_file, size, background, style, type, subtype, newwindow, ext_code

FROM
banners
WHERE
banner_types_id=6
AND lang='eng'
and show=true
AND ((NOT except1 AND '%' LIKE url) OR (except1 AND '%' NOT LIKE url))
AND (CURRENT_TIME BETWEEN fromtime AND totime1) AND (CURRENT_DATE BETWEEN startrotate AND endrotate)
LIMIT 20
[/sql]

-~{}~ 25.09.06 10:41:

апример iBATIS Data Mapper, но он, к сожалению, только для java & .net вроде. Никто не видел что-нибуть подобного для PHP?
dr-sm а что тебе мешает использовать PHP врапперы для .NET или Java
 

bkonst

.. хочется странного?...
Автор оригинала: Alexandre
почему я не использую ОРМ?, простые запросы из жизни,
как это будет выглядеть в терминах ORM?
Ну, например (с поправкой, конечно, на мое понимание данных, используемых в этих запросах):
PHP:
$catalog_filter = new ORMFilterCompositeAND();
$catalog_filter->add_filter(new ORMFilterGreaterThan('cleft', 173));
$catalog_filter->add_filter(new ORMFilterLessThan('cright', 186));
$catalog_filter->add_filter(new ORMFilterEquality('ctype', 3));

$filter = new ORMFilterCompositeAND();
$filter->add_filter(new ORMFilterEquality('object_type', MY_HUMAN_READABLE_OBJECT_TYPE_ID_CONSTANT_EQUAL_TO6));
$filter->add_filter(new ORMFilterBoundObject('Catalog', $catalog_filter));

$items = $manager->itemsFiltered($filter)
,
PHP:
$filter = new ORMFilterCompositeAND();
$filter->add_filter(new ORMFilterBoundObject('Val', new ORMFilterPrimaryKey(202));
$filter->add_filter(new ORMFilterBoundObject('Catalog', new ORMFilterEquality('shortname', '2006clubs'));

$items = $manager->itemsFiltered($filter, 0, 20);
и
PHP:
$exception_filter1 = new ORMFilterCompositeAND();
$exception_filter1->add_filter(new ORMFilterTrue('except1'));
$exception_filter1->add_filter(new ORMFilterLike('%', 'url'));

$exception_filter2 = new ORMFilterCompositeAND();
$exception_filter2->add_filter(new ORMFilterFalse('except1'));
$exception_filter2->add_filter(new ORMFilterNot(new ORMFilterLike('%', 'url')));

$exception_filter = new ORMFilterCompositeOR()
$exception_filter->add_filter($exception_filter1);
$exception_filter->add_filter($exception_filter2);

$filter = new ORMFilterCompositeAND();
$filter->add_filter(new ORMFilterEquality('banner_type', MY_HUMAN_READABLE_TYPE_ID_CONSTANT));
$filter->add_filter(new ORMFilterEquality('lang', 'eng'));
$filter->add_filter(new ORMFilterEquality('show','true'));
$filter->add_filter($exception_filter);
$filter->add_filter(new ORMFilterBetween($current_time, 'fromtime', 'totime1'));
$filter->add_filter(new ORMFilterBetween($current_date, 'startrotate', 'endrotate'));

$items = $manager->itemsFiltered($filter, 0, 20);
Если добавить "синтаксического сахарку", результат будет заметно компактнее.
 

atv

Новичок
whirlwind
А во вторых, даже из той же статьи вы выбрали наиболее подходящее под ваше понимание цитату...
Это естественно. Только точнее сказать, изходя из моего понимания. Каждый человек руководствуется своим пониманием.

И вообще, с какой стати кратенькая статейка, в которой не рассматривается ни одной специфичной проблемы ORM, претендует на роль эталона и абсолютной истины?
Да ни в коем случае. Просто что первое попалось.

Вообще, мы утратили нить разговора. Я уже не понимаю твоих аргументов на мои высказывания.

bkonst
Маппинг объектной модели на реляционную и обратно можно делать по достаточно простым алгоритмам - так как практически любая объектная модель сводится к связям 1:N / N:M.
Это да, но добавьте к этому четыре действия над данными. При выборке нужно правильно связать таблицы, при добавлении и обновлении соблюдать последовательность этих действий для связанных таблиц, ну удаление, наверное, самое простое. Т.е. построитель запросов должен быть достаточно умным. Я не берусь судить, решаема эта задача или нет.

ORM позволяет скрыть это, используя информацию из описания модели.
Неужели пример кода из твоего первого поста читабельнее чем аналогичный SQL запрос. Неужели строчка "new ORMFilterEquality('val', '2')" понятнее чем "WHERE val = 2".

Как с вашей точки зрения, чем обуславливается "неоправданность" применения ORM
1. "Неэффективной реализацией существующих ORM?"
2. Может быть "Невозможностью отображения каких-то запросов на объектную модель?". В общем случае задача вроде как решаема, а проверять на практике нет желания.

====================================================
Вот кстати по последнему примеру. В чём проявляется абстрагирование в случае применения ORM? Условия остаются условиями на любом уровне. Без понимания структуры данных тоже не обойдёшся. Получается только JOIN и заменили, а коду получилось больше.
 

bkonst

.. хочется странного?...
Автор оригинала: atv
Неужели пример кода из твоего первого поста читабельнее чем аналогичный SQL запрос. Неужели строчка "new ORMFilterEquality('val', '2')" понятнее чем "WHERE val = 2".
В том-то и дело, что это всего лишь вопрос синтаксиса конкретной реализации. Это же можно написать, скажем, и как
PHP:
$f->equals('val','2');
или
PHP:
$f->create(a(F_AND,
                     a(F_REF, "Phone", "Property", a(F_EQUALITY,'val','2'))
                     a(F_REF, "Phone", "Property", a(F_EQUALITY,'val','7'))));
или - если "человеко-читабельность" действительно нужна - разобрать строку на собственном "Object Query Language" a-la
Код:
phone.properties[a].val = 2 and phone.properties[b].val = 3
Существенно, что при этом детали (такие как вспомогательные таблицы и искусственные ключи) остаются скрытыми. Меньше рутинного кода - меньше возможность сделать ошибку, которая не будет выявлена в момент проверки синтаксиса.

2. Может быть "Невозможностью отображения каких-то запросов на объектную модель?". В общем случае задача вроде как решаема, а проверять на практике нет желания.
То есть, на практике всё-таки такие запросы или не существуют, или настолько редки, что не приходят на ум с ходу? Это хорошо.
 

dr-sm

Новичок
Тут проблема мне кажется вот в чем:
В результате запроса "выбрать всех активных клиентов"
(это допустим простейший select тра-ля-ля from clients)
мы, следуя канонам об'ектной модели все дела,
должны использовать абсолютно такое же отображение data_row -> object
как и для -
когда захочется чего-нибудь странного (a-la "выбрать всех клиентов, общая сумма покупок которых в категориях товаров, содержащих более чем X наименований, составляет больше N рублей")
И тут существует два пути (используя ORM):
1. Мы не пишем SQL, нам неудобно :D. Зато изголяемся с сотавлением условия для второго запроса,
и исполняется вагон кода чтобы донести до БД собственно, что мы хотели то.

2. Пишем на SQL запрос. он будет выполняться на Data Access Layer и в бизнес логике будет что-то типа:
$clients = $dao->getClients() vs. $clients = $dao->getClientsSpecial4($x, $n).

В обоих случаях получаем результат в виде об'ектов бизнес модели.
Объясните мне плс, зачем на об'ектную модель меппить условие выборки?,
егож можно, как отдельную сущность рассмортеть :).

-~{}~ 25.09.06 11:54:

Автор оригинала: Alexandre
dr-sm а что тебе мешает использовать PHP врапперы для .NET или Java
боюсь тогда танк в ворота не пролезет :D.
 

atv

Новичок
если "человеко-читабельность" действительно нужна - разобрать строку на собственном "Object Query Language" a-la
Ага, и опять вернулись к SQL, только более умному. Может тогда формализовать задачу и решить её в самой СУБД, потому что именно там ей и место.
 

mrjazz

Новичок
Автор оригинала: zerkms
кстати - в теме очень много разговоров ведётся о т.н. "сложных" запросах, которые якобы не сможет разрулить ОРМ.
а можно хотя бы примерное соотношение не сложные/сложные запросы в ваших среднестатистических проектах и собственно 1-2 примера этих самых запросов?
Трезво и по теме. Действительно - почему не перекладывать на ORM рутину а "умные вещи" сочинять "по умному"? Так в принципе и происходит. Особенно если модель вынесена в отдельную абстракцию, плюс ORM допускает ипользование SQL в критических ситуациях. Т.е. и волки цел и овцы сыты.
 

bkonst

.. хочется странного?...
akd

Ага, и опять вернулись к SQL, только более умному. Может тогда формализовать задачу и решить её в самой СУБД, потому что именно там ей и место.
Так в том-то и проблема, что общаемся-то мы с СУБД через SQL, который знает только о реляционной модели, и будет знать только о ней. Приходим к тому, что либо пишем рутинный код руками, либо генерируем этот самый SQL с помощью ORM - а уж что мы скармливаем самой ORM - дело третье. (Переносить бизнес-логику на уровень СУБД? Боже упаси!)

Mich
Там, кстати, именно "интеллектуальный" ORM, способный отслеживать связи самостоятельно:
Код:
l = session.query(User).select_by(street='123 Green Street')
http://www.sqlalchemy.org/docs/datamapping.myt#datamapping_selectrelations
 

whirlwind

TDD infected, paranoid
Alexandre DISTINCT в ORM это отдельная тема. Фактически DISTINCT-а быть не может, т.к. это образует новую сущность, с которой ORM не умеет работать, потому что она не декларирована.

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

PHP:
$banner = new Banner();
$banner->setLimit(20);
$banner->filterBy("banner_types_id",6);
$banner->filterBy("lang","eng");
$banner->filterBy("show",true);
$banner->filterCustom("((NOT except1 AND '%' LIKE url) OR (except1 AND '%' NOT LIKE url))");
По поводу BETWEEN чесслово лишние они тут, потому как заменить их на более простые аналоги можно запросто, при этом особо не напрягаясь. Даже если хочется btw, да наздоровье - кастом фильтр вам в руки.

При этом следует заметить, что вместе с ORM вы абстрагируетесь от конкретных идентификаторов, которые определены в СУБД, за счет алиасов. Вы запросто можете сменить карту псевдонимов и работать фактически с другой таблицей БД и даже, если так хочется, с другими полями. И это - одной строчкой! Для чего это может понадобиться? На вскидку - обернуть существующую таблицу, которая вам совсем не нравится своим названием или названием своих полей. Еще один пример - создание архивной таблицы (кстати, в целях той же самой пресловутой оптимизации), в которую будут переноситься более старые данные. Не трудно прикинуть, сколько строк надо будет вбить, если все писать native sql.

>Опять-таки, насколько, с вашей точки зрения, востребованы такие запросы? И насколько существующие ORM позволяют их реализовывать, не опускаясь к уровню SQL (то есть, насколько востребована такая функциональность)? Лично мне не нравится идея реализации такой обработки на уровне бизнес-логики, так как результатом может стать огромнейшее количество мелких запросов к базе.

Не знаю на сколько существующие ORM позволяют. Могу сказать что в 99% случаев речь идет о контролерах форм. Именно там возникает необходимость комплексно работать с несколькими сущностями.

Вот к примеру кусок лога запросов при выводе списка заказов. Предварительно список id ордеров сделан отдельным запросом с применением соотв. фильтров. Это сделано намеренно - нас не интересует головная боль, связанная с написанием супермегагиперпупермногостраничного запроса. У нас нет на это времени. Мы считаем, что один простой запрос обойдется нам дешевле, чем ломание нашей собственной головы в попытках написать что нибудь эдакое. Примерно такой поток мыслей сопровождает нас всегда. По этому мы все делаем так, что бы позволить ORM работать за нас. Мы думаем - он работает... но это так, отступление.

SELECT * FROM wcmf_tab_order WHERE id = 554

SELECT * FROM wcmf_tab_order_line WHERE owner = '554' ORDER BY line_no

SELECT * FROM wcmf_tab_product WHERE id = 6

SELECT * FROM wcmf_tab_order WHERE id = 555

SELECT * FROM wcmf_tab_order_line WHERE owner = '555' ORDER BY line_no

SELECT * FROM wcmf_tab_product WHERE id = 6
и таких 200 штук. Выполняется и правда не быстро. Но никаких сложных запросов здесь нет! Решение проблемы сводится к BulkLoad 3х сущностей. И ведь правильно получается - объекты работают _в_любом_случае_, а там где скорости не хватает _мы_оптимизируем_работу_. Контроллер - это специфичный объект, мы (программист) об этом знаем, по этому используем средства оптимизации.

Обратите внимание, мы оптимизируем там, где нас не устраивает скорость. В остальном ORM работает за нас. А противники ORM, пишут каждый запрос ручками, независимо от того критична здесь скорость или нет. Хотите сказать нет никакой разницы? Ну тогда можете писать на ассемблере - будет работать еще быстрее, если для вас это так важно. ORM для тех, кто ценит свое время.
 

john.brown

просто кулибин
atv
Может тогда формализовать задачу и решить её в самой СУБД, потому что именно там ей и место.
Так, полагаю, все и рады были бы :) Но суровая действительность такова, что объектные бд пока имеет мизерную распространенность, и жить приходится с тем, что есть... А есть траблы со связкой реляционной бд с объектной моделью - вот и пытаются решить их, кто как может.
Чисто мое имхо, что орм все же есть заплатка на несоответствие хранимых данных их представлению в ооп приложении, и, как таковое, имеет массу недостатков... Но, зато, решает более менее стандартизовано перевод данных в объекты. Что, несомненно, плюс...
 
Сверху