Как я могу разработать веб-приложение Java без ORM и без встроенного [закрытого] SQL

Narowing не работает с динамическим доступом к объекту (доступ с помощью [] и переменной в качестве индекса). Это ограничение связано с производительностью. Вы можете искать в GitHub проблемы, связанные с этим, здесь один.

58
задан johnny 2 June 2014 в 02:03
поделиться

6 ответов

Почему, ох, почему индустрия так привязана к этой катастрофической концепции? Ни один из предыдущих ответов адекватно не решает проблемы @ johnny. Все они - наполовину выдуманные оправдания, которые избегают конкретных проблем, с которыми сталкиваются программисты баз данных.

Ответ @ TheTXI типичен для ответов, которые я получаю, когда задаю тот же вопрос: разделение слоев. Что это должно значить? Почему я хочу, чтобы разделял мои слои? Или, что более важно, какая польза от создания дополнительного уровня, который отличается от реляционного уровня и при этом должен быть каноническим отображением этого уровня?

Кроме того, (пока что оставшийся без ответа вопрос @johhny ) как это защищает нас от изменений? Если база данных изменится, уровень ORM почти наверняка последует этому примеру. Фактически, практика по умолчанию, при которой не моделируются таблицы соединений на уровне объекта, делает это еще хуже, потому что, когда таблица неизбежно вырастает несколько дополнительных столбцов, вы не только добавляете некоторые дополнительные поля в объектную модель, но также меняете ее топологию и принудительно куча кода переписать! Это катастрофа для управления изменениями и классический пример того, как ошибочный взгляд на отношения (думая, что они представляют собой объекты) приводит к катастрофе. Этого просто не произошло бы, если бы вы просто сопоставили реляционную базу данных непосредственно с совпадающими понятиями в языке программирования (подумайте о LINQ-to-SQL, а не , а не LINQ-to-EF).

Самый большой вопрос без ответа в этом пространстве - слон в комнате - это: какую проблему должна решить ORM? И не говорите «объектно-реляционное несоответствие импеданса». Это просто очередной размахивая руками. Объясните, почему существует несоответствие импеданса и почему именно база данных должна обращаться к языку, а не языку, передаваемому в базу данных. Мое объяснение состоит в том, что большинство языков программирования плохо справляются с выражением реляционных данных и работой с ними, но это историческая реальность, которая начинает ускользать (LINQ-to-SQL был первым маленьким шагом в этом направлении), а не фундаментальный принцип на которой основывается звуковая архитектура.

Есть причина, по которой ORM стали такими сложными, с отложенной загрузкой, кешированием, ошеломляющим набором семантики персистентности и владения и т.д. эффективно решать базовые задачи, такие как «Какие пары членов делят более одной группы?» Реляционная модель была задумана в то время, когда сетевые и иерархические модели ломались под тяжестью таких проблем; это был глоток свежего воздуха. Теперь все мы, кажется, жаждем вернуться в нашу старую песочницу, полную кошачьего моча, и думаем, что изобрели что-то новое (пока держим носы).

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

РЕДАКТИРОВАТЬ : Спасибо, @Chris, за то, что нашли время прокомментировать. Это дает мне несколько конкретных вопросов ...(Обратите внимание, что, хотя я часто обращаюсь к @Chris ниже, я не пытаюсь дать ему конкретную задачу; его ответы типичны для тех комментариев, которые я слышу все время при обсуждении темы. Поэтому я надеюсь, что он не принимает мои критика как личное оскорбление; они не предназначены для этого, и я искренне ценю время, которое он потратил на ответ.)

Прежде всего, позвольте мне прояснить некоторые заблуждения, очевидные в комментариях и ответе @Cris.

  1. Я не защищаю необработанный SQL в коде по всем очевидным причинам, а также по некоторым не столь очевидным (например, SQL не является ни алгеброй, ни исчислением, что делает функциональную декомпозицию практически невозможной).
  2. Я не сторонник монолитного проектирования приложений. Слои - это вообще хорошо.
  3. Я не защищаю загрязнение объектных моделей большим количеством линейных помех, таких как специальные поля, методы и атрибуты. Честно говоря, это пустяк, поскольку модели предметной области / объекта существуют только во вселенной ORM. Теперь я знаю, что в LINQ-to-SQL есть все эти классы с большим количеством «зашумленных» битов, но они всего лишь за кадром; вы не редактируете этот код и, как правило, не должны даже смотреть на него.

Теперь некоторые возражения против возражений:

  1. Утверждение, что приложения могут быть построены независимо от базы данных, необоснованно. По большому счету, ORM - это просто каноническое отображение на уровень данных (таблицы Foo и Bar становятся классами Foo и Bar, а таблица FooBar становится своего рода жарким делом между классами Foo и Bar).В этом сопоставлении не так много места для маневра, поэтому любое изменение модели данных почти наверняка потребует соответствующего изменения объектной модели. На мой взгляд, это хорошо, поскольку объект, радикально отличающийся от соответствующей модели базы данных, стал бы не чем иным, как дополнительной головной болью при обслуживании для всех заинтересованных сторон.
  2. Когда иллюзия о том, что ORM порождают независимость от модели данных, отбрасывается, все протесты о вреде прямого связывания с моделью данных становятся спорными. Но я хотел бы продолжить это немного дальше, чем просто отклонить это. Сцепление - важная особенность конструкции системы. В какой-то момент должны быть сделаны решения и предположения. Вы не можете запрограммировать все, используя одну таблицу «Вещи». Вы должны решить, что ваш домен содержит определенные конкретные концепции, а затем создать схемы и код, которые уважают эти концепции, обращаться с ними как с первоклассными гражданами, жестко их кодировать. Идея о том, что приложения должны быть независимыми от базы данных, ошибочна. База данных является (или должна быть) наиболее чистым представлением бизнес-знаний (я знаю, что это не всегда так, и я расскажу об этом позже). Связывание с этим представлением должно обеспечить самую надежную гарантию устойчивости, поскольку такая модель данных будет меняться только тогда, когда сам бизнес претерпевает некоторые внутренние изменения. Короче говоря, привязка к хорошо спроектированной схеме базы данных - это очень хорошо.
  3. Наслоение не является самоцелью. Это хорошо, потому что достигает определенной цели. Предыдущие пункты показывают, что разделение на уровни между базой данных и приложением, как это делает ORM, не является ни эффективным, ни необходимым для достижения реальной цели устойчивости к изменениям. Это достигается за счет хорошего дизайна базы данных.
  4. @Chris утверждает, что позволяя базе данных диктовать вещи, объектно-ориентированный дизайн блокируется. Это верно, но это интересно только в том случае, если объектно-ориентированный дизайн - лучший способ моделирования знаний.Практически полный отказ ООСУБД на рынке указывает на то, что это не так. Реляционная модель, основанная на логике предикатов, обладает той же выразительной силой, что и объектно-ориентированный дизайн, но при этом не требует теоретико-графических сложностей объектно-ориентированных моделей.
  5. Возражения @ Криса против реляционной модели на том основании, что она не решает сегодняшних проблем (отсюда движение NoSQL), совершенно неуместны. NoSQL означает «Нет SQL», а не «Нет реляционной модели». К сожалению, даже сторонники движения NoSQL кажутся совершенно невежественными в этом отношении. SQL имеет глубокие недостатки, многие из которых объясняются его радикальным отходом от реляционной модели. Сказать, что мы должны отказаться от реляционной модели, потому что SQL - отстой, - это довольно вопиющий случай выбросить ребенка вместе с водой из ванны.
  6. Отказ от использования ORM не утроит усилия по созданию приложения. Это смехотворное утверждение, и даже @Chris, кажется, держит заднюю дверь открытой, делая обратный комплимент альтернативе кодогенерации. Инструменты кодогенерации, такие как sqlmetal из LINQ-to-SQL, являются идеальным решением для всех, кто не придерживается догмы о том, что модель данных приложения обязательно должна отличаться от модели данных базы данных.

Мой собственный опыт работы с ORM показал, что они отлично работают в обучающих программах и вызывают бесконечную боль и разочарование в реальном мире. Поскольку LINQ-to-SQL устраняет многие проблемы, которые изначально мотивировали ORM, я не вижу причин подвергать себя таким пыткам.

Остается одна серьезная проблема: нынешний урожай баз данных SQL не предлагает какой-либо значимой степени контроля над разделением физического и логического уровней. Отображение таблицы на содержимое диска в значительной степени фиксировано и полностью находится под контролем СУБД SQL. Это не входило в план реляционной модели, которая явно разделяла эти две модели и позволяла определять согласованное логическое представление данных, которые могли бы храниться на диске в совершенно иной структуре, чем предполагалось в логической модели. Например, система (или dba) может физически денормализовать - по соображениям производительности - сильно нормализованную логическую модель. Поскольку механизмы SQL не допускают такого разделения задач, обычно денормализует или иным образом искажает логическую модель по чистой необходимости. В результате логические модели не всегда могут быть точно такими, какими должны, и поэтому идеал использования базы данных как наиболее чистого представления знаний не может быть полностью реализован. На практике, однако, дизайнеры в любом случае обычно придерживаются канонического отображения базы данных в модель предметной области, потому что все остальное слишком болезненно поддерживать.

118
ответ дан 24 November 2019 в 18:37
поделиться

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

Разделение уровней обычно является целью трехуровневых или n-уровневых приложений, и ORM - хороший способ сделать это.

6
ответ дан 24 November 2019 в 18:37
поделиться

Основной драйвер: меньше общего кода для управления / обслуживания

4
ответ дан 24 November 2019 в 18:37
поделиться

1 вы получаете преимущество в том, что ваш уровень данных отделен от уровня объектов, поэтому, когда у вас есть несколько приложений / проектов в зависимости от этого слоя вы меняете его один раз в ORM, и все приложения / проекты, которые ссылаются на слой объекта, не должны изменяться, тогда как без него вам придется вносить изменения во все проекты.

0
ответ дан 24 November 2019 в 18:37
поделиться

По моему опыту работы с NHibernate, он немного похож на Visual Basic: он упрощает простые задачи на самом деле , но он также делает что-то более сложное, чем это на самом деле сложно или даже совершенно невозможно.

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

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

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

Итак, если вы пишете очень простое приложение, подобное тому, которое вы найдете в учебнике, ORM подойдет. Если это сложнее, то, думаю, оно того не стоит. Конечно, для простого приложения абсолютная экономия времени также будет небольшой. Мой вывод: просто не заморачивайтесь с ORM. ORM - это путь, ведущий на темную сторону.

48
ответ дан 24 November 2019 в 18:37
поделиться

Я подробно ответил на ответ @Marcelo Cantos, однако я резюмирую основные преимущества использования ORM.

Невежество к персистентности (PI) и дизайн привода домена (DDD)

ORM идеально подходит для обоих этих общих шаблонов проектирования. Для правильного объектно-ориентированного дизайна вы будете работать с иерархическими и полиморфными объектами, чтобы выразить поток данных внутри вашего приложения. При хорошем дизайне вы часто будете стремиться к объектам POCO (простые старые объекты C / C #, я видел другие определения этого слова), потому что, если у меня есть человек, у которого есть список, я должен иметь именно его. У меня не должно быть DataTable лиц и DataTable адресов, которые я каким-то образом заставляю работать с моим приложением. Наряду с этим мне не нужно связывать тонны логики конкретной базы данных с моими объектами, почему поле FirstName моего человека должно иметь что-то вроде [ColumnName ("First_Name")] [Length (255)] [DataType (Types.Nvarchar)] или любой другой набор безумных атрибутов или кода, который определяет, сколько существует баз данных, принудительно включенных в мой дизайн домена?

Меньше рукописного кода

Число значительно сокращается строк кода, написанного, когда вы устраняете необходимость писать инструкции Select, Insert, Update и Delete для каждого отдельного объекта в вашем приложении, чтобы сохранить его в базе данных. Это оставляет вам только необходимость писать запросы, которые что-то значат. Также многие ORM (например, NHibernate) будут включать в себя язык, расположенный поверх SQL, который более определен для взаимодействия и может быть менее синтаксически заполнен обручами.

Наиболее полно это проявляется в приложении, у которого есть таблица UserTable, связанная с каждым отдельным объектом, и по какой-то причине вам НЕОБХОДИМО изменить имя или тип первичного ключа. На этом этапе вам потенциально может потребоваться изменить каждую хранимую процедуру в базе данных, где при правильно реализованном решении ORM вам нужно будет изменить только несколько сопоставлений конфигурации (или, возможно, ни одного), и это будет сделано.

8
ответ дан 24 November 2019 в 18:37
поделиться