Для чего нужна ORM?

Нет, я не пойму зачем заменять SQL язык своим?
Зачем надо делать класс, методы которого принимают имя таблицы, принимают условие для фраз WHERE, GROUP BY, HAVING.

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

Так в чём профит?
2 июля 2011 в 01:12
6
OlegTar 18,6

отсортировано по дате по оценке
ответы (13)

+5
VolCh #
Вы не путаете ORM с DBAL? ORM это не технология замены SELECT * FROM goods WHERE cost < 100.00 на $db->select()->from('goods')->where('cost < 100.00'). ORM это способ задания связи объектов и РСУБД. По сути позволяет абстрагироваться от способа хранения объектов вообще, с лёгкостью переходя от SQL к NoSQL, memcache, файлам или REST/RPC API на удалённом сервере, оперируя на уровне модели (если говорить о MVC и т. п.) простыми plain old objects, а их персистентность отдать контроллеру. Не $db->select()->from('goods'),, не mysql_query('SELECT * FROM goods'), а $goodsRepository->findAll(), а уж будет репозиторий формировать SQL запрос, читать файлы или память, а может стучаться на Гугл и парсить его вывод — его, репозитория, личное дело (а также разработчика(ов), отвечающих за подсистему хранения).

Кроме того ORM, как правило не исключает обращение к БД на уровне произвольных SQL запросов, оно лишь преобразуют результаты этих запросов в объекты модели предметной области (и наоборот), которые ничего не знают (в идеале) о таблицах, WHERE, HAVING и т. п.

ORM это не только инструмент архитектурного разделения областей ответственности объектов и классов приложения, а также инструмент облегчения разделения труда разработчиков: кто хорошо шарит в SQL вообще и особенностях конкретного движка в частности — работает по «ту сторону» ORM, оптимизирует его как хочет, может нормализовывать и денормализовывать, например; кто хорошо разбирается в дебетах и кредитах — работает с plain old objects в терминах предметной области и может вообще ничего не зная об SQL, ему лишь нужно знать, что он всегда может получить объект или их коллекцию обратившись к методам вроде findById() или findAll() и сохранить результат работы методом save() или flush().
Спасибо. Очень понятно. Понял, что ORM я путал с DBAL. OlegTar, 2 июля 2011 в 21:11
Т.е. если я в своем проекте напишу функцию findAll(), которая возвращает все товары, то это уже можно считать ORM? pihel, 2 июля 2011 в 23:03
это даже не dbal, а паттерн builder, в данном контексте query builder, он не болько помогает обстагироваться от типа стораджа, но и собирать запрос по частям, например, с учётом if-оф и переданных параметров.

кстати. типичная ошибка — применения билдеров в контроллерах, а не в отдельном-классе модели.

2 pihel
это будет ORM, если ты сможешь динамически доставать ти изменять связанные данные, например, категория товаров.

$products = Products::findAll();
$category = $products[0]->get('Category');
$category['name'] = 'new name';
$category->save();
AmdY, 3 июля 2011 в 06:05
+6
simplecode #
некий интерфейс для работы с данными, которые не важно в каком виде и где находятся… в коде очень удобно работать с объектом, который представляет некоторый набор данных…
+1
Melanitsky #
Для простых запросов это удобней. Вы просто собираете запрос как конструктор, INSERT и UPDATE также невероятно удобен. Просто передать ассоциативный массив в качестве аргумента. По крайнем мере так в Zend_DB.
А сложные и вложенные запросы все ровно приходиться писать ручками.
–1
WebByte #
По моему скромному мнению, ORM придумали люди, которым сложновато мыслить теорией множеств, что необходимо для понимания и правильного применения SQL.

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

Как всегда, рекомендую статью:
citforum.ru/database/articles/vietnam/
Вот пример почему это удобней. Часть метода с выборкой товаров с помощю ORM с условием.
/***/
$select = $db->select()->from('goods');
$select->join('pages', 'pages.idPage = goods.idPage');
if ($route) {
$select->join('routing', 'pages.idRoute = routing.idRoute');
}
if ($content) {
$select->join('content', 'content.idContentPack = pages.idContentPack');
$select->where('content.idLang = ?', Kernel_Locale::getCurrent()->getId());
if ($search) {
$select->where('content.contentName = ?', $search);
}
}
if (!$expired) {
$select->where('goods.goodExpirationDate > ?', time());
}
if ($photo) {
$select->join('photos', 'goods.idPhoto = photos.idPhoto');
}
$select->where('pages.pageType = ?', self::TYPE_GOOD);
if ($idCatalog) {
$select->where('goods.idCatalog = ?',$idCatalog);
}
if ($idCategory) {
$select->where('goods.idCategory = ?',$idCategory);
}
if ($idCity) {
$select->where('goods.idCity = ?',$idCity);
}
/***/
Melanitsky, 2 июля 2011 в 01:50
Мог бы — поставил бы 10 плюсов!!! Реально, в последнее время orm/activerecord — скорее минус программисту, чем плюс. Ни разу еще не видел, чтобы от orm была реальная польза проекту. Экономия в 5-10 минут и потом 30-40 минут на переписывание модуля — такое встречаю уже довольно часто =( aktuba, 2 июля 2011 в 02:08
Ересь какая-то, Linq являет собой практически тот же самый sql, от использования ORM ничего не меняется. Приглашаю к обсуждению: habrahabr.ru/qa/9097/#answer_38782 kefirr, 2 июля 2011 в 11:02
2Melanitsky, это разве orm? Это же конструктор запросов. quantum, 2 июля 2011 в 11:37
Спасибо. А от Скрама польза всё-таки есть. Я работал по нём, главное всё по методологии делать. OlegTar, 2 июля 2011 в 21:07
0
variable #
Тот-же самый фреймворк, только для базы. Использование фреймворков не оправданно?
Оправдано, только методы, которые принимают в качестве параметров имя таблицы, условие where и group by по сути те же селекты.

P.S.
я вижу хороший пример от WebByte. simplecode привёл пример про объекты, это полезно.
OlegTar, 2 июля 2011 в 03:21
+7
phasma #
> Так в чём профит?

Вы пробовали поддерживать проект, который поддерживает 5-6 СУБД?
нет. теперь понял. OlegTar, 2 июля 2011 в 03:25
Для поддержки нескольких СУБД можно использовать cayenne.apache.org/. Он поддерживает возможность писать запросы для каждой из поддерживаемых СУБД. Затем, сам определяет что за СУБД и подтягивает нужный запрос. Очень удобно, когда нужна максимальная производительность запросов (например, указание в запросах каки-то хинтов, индексов и т.д.) SergeyGrigorev, 2 июля 2011 в 03:54
Забыл написать, cayenne только для Java. Для других языков наверное есть «свои кайены». Как ORM мы его не используем, только для того, чтобы можно было писать запросы, учитывая синтаксис каждой из поддерживаемых СУБД SergeyGrigorev, 2 июля 2011 в 03:57
Это модификация единственного кажущегося более-менее адекватным ответа на вопрос: «При переходе проекта на новую СУБД не придется переписывать код». Правда, обычно его приводят как аргумент люди, которым не доводилось подобное действие совершать. Либо которые имеют слабое представление о возможностях той или иной СУБД.

Так вот — при подходе к работе с базой как к чуть более сложному механизму, чем просто хранилище, становится понятно, что даже SQL-синтаксис похож лишь в базовых конструкциях. И отдавать на откуп ORMу даже конструирование запросов — зачастую смерти подобно. Сильно сомневаюсь, что без знания о том, какие у меня данные ORM адекватно сможет определить какую из подобных конструкций нужно использовать в том или ином случае:

SELECT id FROM foo ORDER BY bar;

SELECT /*+index_asc(foo_bar_id) */ FROM foo;

SELECT * FROM foo WHERE rownum <= 10;

SELECT * FROM ( SELECT f.*, rownum rn FROM foo f ORDER BY id ) WHERE rn <= 10;

SELECT f.*, row_number() over (ORDER BY id) rn FROM foo f HAVING rn <= 10;
WebByte, 2 июля 2011 в 13:43
+1! Zorkus, 3 июля 2011 в 11:41
+1
kirsan_vlz #
У меня в проекте есть много однотипных модулей, которые представляют объекты. Можно выбирать из базы один объект, можно выбирать много объектов. Всё это по любому полю или совокупности полей. И вот раньше приходилось на каждый такой модуль писать кучу однотипных запросов для всех этих действий. После внедрения ОРМ стоит только добавить несколько строк настройки в модуль и все эти методы сразу становятся доступны. То есть разработка становится быстрее за счёт устранения рутины. Совсем уж сложные запросы пишем, само собой на чистом SQL, а вот простые ORM выполняет на ура.
+2
smartly #
Чтобы писать запросы на своём языке программирования, а не интегрировать в исходник ещё один язык.
0
kefirr #
Что значит — зачем? Чтобы представлять результаты запросов в виде объектов языка. А как ещё вы предлагаете работать с результатами запросов?

Давайте предметно рассуждать. Покажите код, который делает запрос и показывает результаты пользователю. И посмотрим, можно ли этот код сделать лучше при помощи ORM.

PS Я работаю с Entity Framework 4.0, и он великолепен.
И посмотрим, можно ли этот код сделать лучше при помощи ORM.

«Лучше» — это как? Быстрее? Читабельнее?
WebByte, 2 июля 2011 в 13:51
Спасибо. По ответу Volch я понял, что я путал ORM с DBAL. OlegTar, 2 июля 2011 в 21:12
0
freeAKK #
ORM нужен тогда, когда время жизни объектов выборки сильно больше чем время самой выборки. В таких случаях затраты на выборку объектов со всеми потрохами (JOIN-ы) незначительно сказываются на скорость, а сохранить состояния объектов очень просто. Т.е. потребность в ORM возникает в «долгоживущих» программах, в которых РСУБД это просто место, где мы можем сохранить свои объекты.
В случаях, когда нужно отработать быстро, sql (DBAL) незаменим.
Понял. OlegTar, 3 июля 2011 в 12:28
Спасибо. OlegTar, 3 июля 2011 в 12:28
+4
Zorkus #
Сам по себе ORM, именно как maaping, в крупных проектах нужен как раз очень сильно. Опишу здесь свой опыт. Если понравится кому, может и статью потом.

Итак.
Представьте себе — у меня есть очень крупная система, и есть в ней таблица orders, в ней скажем, 50 колонок (на самом деле у нас 150, ну да ладно. Нормализаторы, молчать! Про нормальные формы я тоже знаю). И вот надо значит вам выбрать один ордер и показать его на экране. Допустим, вы пишете селект, неважно. Дальше что делать, в промежуточном слое? Вы не же вызываете хранимую процедуру (запрос) напрямую с, скажем, JSP страницы (я надеюсь), вам все равно надо получить данные и передать их как-то.
Так что, передавать их в виде массива, ArrayList-a, ассоциативного массива имя колонки/значения? Ну так дико громоздно, неудобно, и очень легко ошибиться. А если вам надо несколько ордеров, тогда что, создавать вложенные коллекции для конвертации результатов? Неудобно же.

Потому, очевидно, нам нужен объект Order, имеющий все нужные property, и нужен код, который умеет конвертировать результаты скл запрос в эти объекты (или коллекцию этих объектов).

Далее, очевидно, что писать руками _все_ запросы трудно и нудно, легко ошибиться, т.к. в Java они будут представляться в коде в виде строк (а значит, никакой статической типизации и compile-time проверок и прочее и прочее), и их надо держать либо в Java коде (если они мелкие), либо, если побольше, выносить в отдельные XML файлы.

В общем, ORM в больших проектах нужен для упрощения рутинной части. Без него — никуда :)

Безусловно, обойтись ТОЛЬКО ORM не получится. Есть у нас масса мест, где сложная логика написана в хранимых процедурах в 500-1000 строк на PL/SQL, написанная через ORM /Java она бы занимала в 10 раз больше и работала в 2 раза медленнее (при этом, она была бы еще и менее понятная, т.к. есть такая логика, которые в терминах реляционной алгебры описывается куда проще, чем в терминах ООП :), следовательно ложится на ORM со скрипом). Сколько нибудь сложные запросы с подзапросами, юнионами, хитрыми джойнами тоже писать через чистый ORM громоздко. Оптимизировать запросы, работающими в таблицах где, хотя бы, несколько сотен миллионов записей, без доступа к планам SQL оптимизатора и статистики/средствам мониторинга уровня СУБД тоже крайне сложно. Так что без SQL тоже — никуда :)
Да, и еще. Я ни слова не сказал тут о совместимости с разными СУБД, т.к. это часто ненужное требование. Большие и сложные системы активно использует СУБД-specific фичи, и требования писать скл-код, совместимый с Oracle/MSSQL/DB2 часто не ставится. Все понимают, что это — огромное усложноние и удорожение, далеко не всегда оправданная. Подлинная независимость от серьезного вендора — стоит дорого, очень дорого. А часто ли она реально нужна? Zorkus, 3 июля 2011 в 11:39
Спасибо. Я понял, что ORM — это больше создание объектов, а не создание запросов. Я стараюсь выносить селекты в PL/SQL-ные пакеты.
А насчёт поддержки разных баз согласен, не нужно стремиться поддерживать разные базы.

Вообще по моему наблюдению складывается впечатление, что те, кто работал с Ораклом начинают относится к базе,
не как к простому хранилищу данных,
а те, кто не работал с Ораклом, относятся к базе данных как к простому хранилищу.

Может это из-за того, что нету авторов таких, как Том Кайт, для других баз данных.
OlegTar, 3 июля 2011 в 12:31
Относиться к ораклу как к простому хранилищу :) Ну не знаю, какая аналогия вам ближе, это все равно что купить Hasselblad или хотя бы «однозначный» Canon снимать в автоматическом режиме. C Oracle нельзя работать, зная о базах данных столько, сколько знают средние, извинити меня ради бога, веб-разработчики. Zorkus, 3 июля 2011 в 12:38
+1
Zorkus #
написал статью тут — habrahabr.ru/blogs/programming/123293/
Не согласен по многим пунктам. Хотя сталкивался с Enterprise-проектами неоднократно.
Правда, не c Java в качестве языка.
Может быть именно поэтому нет необходимости работать со всем как с объектом.
WebByte, 5 июля 2011 в 23:15
C чем именно не согласны, отпишитесь тогда там в комментах? Zorkus, 9 июля 2011 в 15:50
0
pil0t #
Используем C#, DataObjects.Net
ORM с методолгией CodeFirst значительно упрощает поддержку БД.
Примеры:
1. Удалили поле из таблицы — нам нужно каким-то хитрым образом проверить все запросы которые могут использовать это поле. В случае работы через ORM мы уже на этапе компиляции не сможем написать неправильный запрос.
2. Переименование поля — при ORM можем пользоваться всеми возможностями таких штук как Resharper, и автоматом переименовывать там где надо.
3. Не самая высокая оптимальность запросов через ORM частично компенсируется возможностью кэширования на appserv, а так же возможностью выполнения части запросов на appserv (с учетом легкой масштабируемости последнего)
4. В качестве доп. бонуса, хотя и не особо используемого нами — получаем переносимость на другие БД
Проще было написать, что нормальные ORM в нормальных языках упрощают поддержку проекта :) ArtyV, 3 июля 2011 в 20:24
Удалили поле из таблицы

Нормальная СУБД проверит зависимости и инвалидирует пакеты/процедуры.

Переименование поля

Переименование поля в СУБД, где SQL позволяет делать alias'ы вообще не понятно зачем нужно.

Не самая высокая оптимальность запросов через ORM частично компенсируется возможностью кэширования
Большинство СУБД кешируют и сами запросы, и данные, которые они возвращают. Не уверен, что разработчик средней руки реализует какой-нибудь LRU механизм лучше, чем разработчики СУБД.

переносимость на другие БД

Гы-гы-гы, когда у вас в крупном проекте возникнет такая задача, это скорее всего будет означать, что пора выкидывать ORM и начинать закупать железо. Менять хранилище данных от нечего делать — глупо, а при проблемах означает, скорее всего, то, что придется отказаться от плюшек ORM и начать работать с напильником
WebByte, 5 июля 2011 в 23:11
Именно переименование делать приходится иногда — на одних алиасах и синонимах не всегда далеко уедешь. Zorkus, 9 июля 2011 в 15:51

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