После использования Hibernate в большинстве моих проектов в течение примерно 8 лет я попал в компанию, которая не одобряет его использование и хочет, чтобы приложения взаимодействовали с БД только через хранимые процедуры.
После того, как я делал это в течение нескольких недель, я не смог создать богатую модель предметной области приложения, которое я начинаю собирать, и приложение просто выглядит как (ужасный) транзакционный скрипт.
Некоторые из проблем, которые я нашел:
- Невозможно перемещаться по графу объектов, так как хранимые процедуры просто загружают минимальный объем данных, а это означает, что иногда у нас есть похожие объекты с разными полями. Один из примеров: у нас есть хранимая процедура для получения всех данных от клиента, а другая - для получения информации об учетной записи, а также несколько полей от клиента.
- Большая часть логики заканчивается вспомогательными классами, поэтому код становится более структурированным (с сущностями, используемыми в качестве старых структур Си).
- Более скучный код скаффолдинга, так как нет структуры, которая извлекает наборы результатов из хранимой процедуры и помещает ее в сущность.
Мои вопросы:
- кто-нибудь был в подобной ситуации и не согласен с подходом к процедуре хранения? что ты сделал?
- Есть ли реальная выгода от использования хранимых процедур? кроме глупой точки «никто не может выпустить дроп-стол».
- Есть ли способ создать богатый домен с помощью хранимых процедур? Я знаю, что есть возможность использовать AOP для внедрения DAO / Repositories в сущности, чтобы иметь возможность перемещаться по графу объектов. Мне не нравится этот вариант, так как он очень близок к вуду.
Вывод
Во-первых, спасибо всем за ваши ответы. Я пришел к выводу, что ORM не позволяют создавать модели Rich Domain (как упоминали некоторые люди), но это упрощает объем (часто повторяющихся) работ. Ниже приведено более подробное объяснение заключения, но оно не основано на каких-либо достоверных данных.
Большинство приложений запрашивают и отправляют информацию в другие системы. Для этого мы создаем абстракцию в терминах модели (например, бизнес-событие), а модель домена отправляет или получает событие. Событию обычно требуется небольшое подмножество информации из модели, но не вся модель. Например, в интернет-магазине платежный шлюз запрашивает некоторую информацию о пользователе и общую сумму, которая взимается с пользователя, но не требует истории покупок, доступных продуктов и всей клиентской базы. Таким образом, событие имеет небольшой и конкретный набор данных.
Если мы берем базу данных приложения в качестве внешней системы, то нам нужно создать абстракцию, которая позволяет нам отображать сущности модели домена в базу данных ( как упомянул НимЧимпски , используя средство отображения данных). Очевидное различие заключается в том, что теперь нам необходимо вручную сопоставить для каждой сущности модели базу данных (либо унаследованную схему, либо хранимые процедуры), при этом возникает дополнительная проблема, заключающаяся в том, что, поскольку эти два объекта не синхронизированы, одна сущность домена может отображаться частично к объекту базы данных (например, класс UserCredentials, который содержит только имя пользователя и пароль, сопоставлен с таблицей Users, имеющей другие столбцы), или один объект модели домена может отображаться на более чем один объект базы данных (например, если существует однозначный одно отображение на таблицу, но мы хотим, чтобы все данные были только в одном классе).
В приложении с несколькими сущностями объем дополнительной работы может быть небольшим, если нет необходимости перемещать сущности, но он увеличивается, когда возникает условная необходимость пересечь сущности (и, таким образом, мы можем захотеть реализовать своего рода «ленивый»). загрузка '). По мере того, как в приложении растет число сущностей, эта работа только увеличивается (и у меня есть чувство, что оно увеличивается нелинейно). Здесь я предполагаю, что мы не пытаемся заново изобрести ORM.
Одно из преимуществ обработки БД как внешней системы заключается в том, что мы можем кодировать ситуации, в которых нам нужны 2 разные версии приложения, в которых каждое приложение имеет свое сопоставление. Это становится более интересным в сценарии непрерывных поставок в производство ... но я думаю, что это также возможно с ORM в меньшей степени.
Я собираюсь отклонить аспект безопасности на том основании, что разработчик, даже если он не имеет доступа к базе данных, может получить большую часть, если не всю информацию, хранящуюся в системе, просто путем внедрения вредоносного кода (например, Я не могу поверить, что я забыл удалить строку, которая регистрирует данные кредитной карты клиентов, дорогой лорд! ).
Небольшое обновление (6/6/2012)
Хранимые процедуры (по крайней мере, в Oracle) не позволяют делать что-либо, например, непрерывную доставку с нулевым временем простоя, поскольку любое изменение структуры таблиц приведет к аннулированию процедур и триггеров. Поэтому во время обновления БД приложение также будет недоступно. Oracle предлагает решение для этого, называемого Переопределение на основе редакции , но несколько администраторов баз данных, которых я спрашивал об этой функции, отметили, что она плохо реализована и не поместит ее в рабочую БД.
Ответы:
Ваше приложение по-прежнему должно быть смоделировано на основе принципов проектирования, ориентированных на домен. Используете ли вы ORM, прямой JDBC, вызывая SP (или что-то еще), не имеет значения . Надеемся, что тонкий слой, абстрагирующий вашу модель от SP, поможет в этом случае. Как сказал другой участник , вы должны рассматривать SP и их результаты как сервис и сопоставлять результаты с вашей моделью домена.
источник
В финансовом мире (и в местах, где требуется соблюдение закона Сарбейнса-Оксли ), вы должны иметь возможность проводить аудит систем, чтобы убедиться, что они делают то, что должны. В этих случаях гораздо проще обеспечить соответствие, когда весь доступ к данным осуществляется через хранимые процедуры. А когда весь специальный SQL удален, скрыть все гораздо сложнее. В качестве примера того, почему это было бы «хорошо», я отсылаю вас к классической статье Кена Томпсона « Размышления о доверии» .
источник
Хранимые процедуры намного более эффективны, чем и клиентский SQL-код. Они предварительно компилируют SQL в БД, что также позволяет ему выполнять некоторые оптимизации.
Архитектурно, SP возвратит минимальные данные, необходимые для задачи, что хорошо, поскольку означает, что передается меньше данных. Если у вас есть такая архитектура, вам нужно думать о БД как о сервисе (думать о нем как о веб-сервисе, а каждый SP - это метод для вызова). Работать с ним таким образом не должно быть проблемой, в то время как ORM поможет вам работать с удаленными данными, как если бы они были локальными, и, таким образом, обманом заставит вас столкнуться с проблемами производительности, если вы не будете осторожны.
Я был в ситуациях, когда мы полностью использовали SP, БД предоставила API данных, и мы использовали его. Это конкретное приложение было очень масштабным и работало на удивление хорошо. Я не скажу ничего плохого о СП после этого!
Есть еще одно преимущество: администраторы баз данных напишут все ваши запросы SQL для вас и с радостью будут обрабатывать всю реляционную иерархию в БД, так что вам не нужно это делать.
источник
the approach of letting the DBAs write the procedures smells like development silos
+100 интернетов к тебе за этот камень правды. Я всегда видел это как случай, когда доступ к данным контролировался с помощью хранимых процедур.Часто случается, что разработчики неправильно используют свои объекты ORM в качестве моделей своих доменов.
Это неверно и привязывает ваш домен напрямую к вашей схеме БД.
Что должно быть на самом деле, так это раздельные доменные модели, настолько богатые, насколько вам нравится, и использование слоя ORM отдельно.
Это означает, что вам потребуется сопоставление между каждым набором объектов.
источник
Ваши доменные объекты могут быть заполнены, как вам угодно, не обязательно использовать Hibernate. Я думаю, что правильный термин - картограф данных . Вполне возможно, что ваши постоянные данные будут полностью отличаться по структуре от ваших доменных объектов.
источник