Думаю, вашу логику, которую Вы описали выше, можно не реализовывать в вашем коде вообще. При работе с СУБД это можно выполнить на чистом SQL. В подавляющем числе случаев в своем коде я так и делаю.
Записываем (подготавливаем все для записи - это может быть ArrayList, Vector, массив) ваш JSON в БД. С этим справится и мой универсальный сервис. И дополняем SQL выражениями, которые и отработает вашу логику. И отдаем все на выполнение в одной транзакции.
Для этого нужно только слегка изменить код моего универсального сервиса, который добавить в подготовленный набор модификации базы требуемые SQL. Если эти SQL вынести еще в свойства приложения, то модифицируемость вашего приложения резко повысится. Вы можете часть новых требований отработать только изменениями SQL в свойствах приложения не затрагивая ваш код. Если учесть, что мой код "универсального" сервиса автоматически отработает любые изменения структуры JSON, если таковые возникнут, то вообще сказка получается.
Представляете, возникло требование - увеличить число полей в JSON, то Вы просто добавляете поля в таблицу/таблицы, в случае необходимости меняете SQL в свойствах - и все. Ваш код без каких либо правок работает с новыми требованиями.
Вы продолжаете мыслить реализацией класса Cart, отсюда и возникает у Вас вопрос как его куда то передать? Вы же где то у себя в коде его создали и заполнили его поля откуда то взятыми данными. Вот "откуда то" и нужно смотреть как это передать на сохранение.
Взгляните на свой класс Cart, CartItem и прочие подобные классы. Взгляните на код, который манипулирует этими классами. Не возникает мысли, что постоянно пишите один и тот же код, в котором отличаются по сути только используемыми именами классов и методов? Если не возникает, ну что ж пишите и дальше.
А я вам уже много раз подчеркивал, что цель именно в том, чтобы сделать не любые, а соответственно ограничениям в требованиях. ORM нужна для этой цели. Мне не нужно написать код для сохранения произвольных структур данных, мне нужно написать именно код создания заказа, вызывая в нем код для сохранения произвольных структур данных. Это будет другой код, а не тот, который вы привели. В вашем коде создания заказа по нужным правилам нет, он будет создавать заказ по любым правилам, например сразу оплаченным.
Так в чем проблема добавить какую то логику или ограничения? Нет проблемы. Если в вашем коде это реализовано, то почему Вы считаете, что подобную логику нельзя добавить в код моего примера? Я Вам показал идею, как можно уменьшить объем кодирования и повысить модифицируемость приложения. Хотите пользуйтесь, хотите нет. А уж какой логикой наполнить эту идею, извините, это уже ваша "головная боль". В своем же коде Вы это делаете по шаблону вашего движка, думаю и в моем варианте можете справиться.
Вот я вам и объясняю, что тогда ORM будет в этой логике. И просил вас показать пример, как вы эту логику будете добавлять без ORM. Что вы так и не смогли сделать.
В логике вашего приложения не ORM, а реализация ваших классов Cart, CartItem и всех прочих, которые являются некоторым представлением предметной области. Это представление можно реализовать каким то другим программным кодом и на его основе реализовать вашу логику. Можно? Можно.
Кода нет, разговаривать не о чем.
Я понятие не имею какую логику вы хотите чтобы я реализовал. И возникает вопрос, зачем мне это нужно делать?
Я не знаю, что вы имеете виду под MAP-классами, но там во втором абзаце написано "This could be modeled in an object-oriented implementation by a "Person object", где Person является одним из этих "различных классов".
MAP классы - это то, что программно реализует соответствие одного другому. И если Вы эти классы не используете явно, то ваш движок, реализующий ORM, без них не будет работать.
Какая разница что это класс Person, Cart, CartItem или любой другой класс аналогичного назначения. Главное, что эту классу Person ставится в соответствие таблица Person, которая по количеству полей может 100% соответствовать полям класса Person. В этом корень проблемы !!! Т.е. Вам нужно для каждой таблицы и возможно представлению создавать собственный класс отображения. И совершенно не важно сгенерирован этот код по структуре таблицы или Вы его напишите в ручную. Этот код есть в вашем приложении. Добавляете таблицу - добавляете новый класс. Добавляете поле - добавляете новые методы в класс. Добавили методы - корректируете другой код для вызова этих методов. Зачем? Если можно это не делать. И сразу куча плюсов. Меньше кода, легче модифицировать ПО, а при добавлении поля можно вообще код не модифицировать. Добавил поле, перезапустил приложения - красота.
Ага, все люди не знают, что они называют этим термином, один вы знаете. Нет, термин "mapping" там находится не просто так. ORM делает именно mapping. Например, поле "user.user_id" из базы может замапить на "User.user_id", "User.userId" или "User.lalala" в коде.
Да какая разница в какое поле таблицы записывается какое именованное значение? Никакой. Я же Вам писал, что разработка ПО это прежде всего выработка соглашений. Вырабатываете соглашение, что имена значений должны совпадать. Отклонения от соглашения, например, прописали в конфиге приложения. Не нравится конфиг пропишите в коде на худой конец. Целую кучу кода Вам не лень писать, а небольшие отклонения которое отправит эту кучу кода в корзину в лом?
Все источники данных указаны в моем коде. Это inputDto, currentUser и системное время.
Хорошо, пусть будет источник данных или результат преобразования источника данных.
Нет. Я уже 10 раз вам объяснил, не все данные приходят снаружи от пользователя в виде хешмапов. Если у вас приходят все, значит это очень простое приложение, и вам не нужна ORM.
Хорошо, хешмапы так хешмапы. Если заметили, в моем примере входные данные в виде JSON или XML тоже преобразуются в хешмап, следовательно ваши данные моим "универсальным" кодом тоже успешно могут быть обработаны. Ни что не запрещает Вам в любом программном слое расширять полученный входной набор любыми другими дополнительными атрибутами, если в этом есть необходимость.
Я вам уже ответил на это утверждение. Я серьезно не понимаю, с какой целью вы повторяете одно и то же, игнорируя ответы. В коде вашего проекта ORM и не нужна, потому что в нем нет никакой логики. ORM будет в том коде, который будет работать с вашим сервисом.
Логика приложения это отдельное преобразование входных данных. Еще один кубик/слой. Преобразованные в хешмап (в вашем понимании) входные данные передаются кубику "логика приложения", который либо возвращает модифицируемый хешмап, либо другую структуру программному слою "запись в БД". Все просто. Если Вам или кому то другому вдруг когда придется менять логику приложения, то нужно модифицировать или полностью заменить в коде только кубик.
Вы похоже так и не поняли. Попробую еще один раз объяснить. "Создание программных типов" нужно не для сохранения в базу, а для человека. Чтобы программисту было удобнее работать с кодом. Программист работает с кодом до старта приложения.
Заблуждение. Вам это нужно только из-за того, что Вы используете фреймворк, который реализует идеологию ORM. Смените свой фреймворк.
Ну преобразуйте. Почему вы с вашим подходом 10 строк написать не можете? С ORM я уже 2 задачи решил, а вы без ORM второй день рассуждаете, и ни одной задачи не решено. Так вы покажете код создания заказа, или официально отказываетесь подтвердить свои слова делом?
Мне даже одной сточки писать не нужно. Много раз уже подчеркивал, мой пример будет работать с любой базой и модифицировать любые структуры в них. В том числе и с вашей. вашу логику в него добавить и можно полностью заменить ваше приложение.
ORM - Object Relational Model с моей точки зрения более точная расшифровка, чем Object Relational Mapping. Термин "mapping" Вас похоже и вводит в заблуждение. Даже ваша ссылка дает определение, в котором речь идет о реляционной модели данных и программной модели. Т.е. к различным MAP-классам термин ORM не имеет какого либо отношения.
По поводу "7-уровневой модели IP стека". Если теоретическая 7-уровневая модель на практике по каким то причинам реализуется в 6, 5, 4 - уровня, что это меняет? Главное что каждое ПО нужно пытаться разбить на уровни.
ORM мешает разбивать приложение на уровни, каждый из которых должен иметь узкую специализацию. ORM привел в качестве очень плохого решения.
Чем больше узкоспециализированных уровней в приложении, тем легче отвечать на самые неожиданные требования в процессе всего жизненного цикла этого приложения.
Данные, которыми Вам нужно манипулировать, откуда то же берутся? Берутся. Назовем это "источник данных". Какой именно "источник данных" совершенно не важно, это пользовать, сервис, событие или что то еще. У этого "источника данных" есть соглашения - имена и формат данных каждого поля? Есть. Если Вы в состоянии повлиять на это соглашения, то нужно составить соглашение таким образом, чтобы Вам было удобно с ними работать. Если не влияете, то можно подстроит свою модель данных в БД так, что так же с ними можно было удобно работать. Далее принимаете данные из "источника данных" и передаете их блоку/слою/кубику "манипулирование данных", который сохраняет результат в БД. Все просто. И совершенно не важно из какого источника данные получены и совершенно не важно какие манипуляции выполняются.
Из-за того что Вы не правильно понимаете идеологию ORM и возникает не понимание. Ваши классы Cart, CartItem и любые другие это программная (объектная) модель. Структура хранения данных в БД - это модель данных. ORM задает жесткую связь между двумя разными представлениями одной и той информации в разных макрослоях информационной системы, в частности в слое хранения данных и слое приложения - объект имеет отображение в модели. Это отображение фактически объединяет два совершенно разных макрослоя в одни (один без другого теряют какой либо смысл). Это очень плохо с точки зрения реализации и модифицируемости, писать кода надо много, вносить изменения тяжело.
В моем примере нет этой связи между моделью (БД) и объектами (программным кодом). Мой пример будет работать с любой базой. И еще раз подчеркиваю, ЭТО ПРИМЕР - который демонстрирует возможность работы без ORM. В этом примере используется программный слой манипулирования любыми данными (см поле database класса TableService). Этому программному слою все равно что выполнять, работать с одной таблицей или сразу во множеством.
Бизнес требования - это функциональные требования. Разные разработчики могут совершенно по разному преобразовать эти требования в программную модель приложения и структуры хранения. Так что это к обсуждаемой теме не относится.
В БД есть понятие метаданных, которые описывают всю структуру БД - таблицы, поля, типы, ключи и т.д. БД предоставляет API для получения этой информации. Не нужно гадать какая структура таблицы или какой PK этой таблицы. Можно спросить у БД, она ответит. И все. Необходимость программного описания (создание программных типов) отпадает. Обычно, при старте приложения идет опрос метаданных, по этим данным можно сразу или по мере необходимости генерировать SQL выражения. Смотри сразу сколько кода не нужно писать. И самое интересное, этот код можно использовать повторно в других проектах.
Мои доказательства опубликованы в GitHub-е - пример реализации универсального сервиса. Работает с любой БД и не нужно добавлять ни одной строчки кода. В вашем варианте нужно на любой чих писать "10 строк кода". Подчеркиваю НА ЛЮБОЙ. Причина - в том, что вашем коде заложена жесткая связь между моделью данных (предположу, что таблица CART) и программной моделью (классом CartItem). Класс CartItem 100% или с небольшими отличиями повторят структуру таблицы CART - это и есть ORM. При изменении таблицы CART вам нужно изменить класс CartItem или на оборот.
То что Вы считаете ORM таковым не является. Думаю, что и под виртуальной БД Вы понимаете не виртуальную БД.
У Вас эти "10 строк" применимы только в конкретном месте, в другом месте Вам нужно повторить эти "10 строк" и так везде, где Вы работаете с БД - постоянно повторяете один и тот же код с небольшими отличиями в основном в именах и специализированных типах данных (программной модели - O), которая должна соответствовать структуре таблиц (модели данных - М). Иными словами - программная модель (O) соответствует (R) модели данных (M), что и называется ORM.
Если отказаться от использования ORM то
не нужно постоянно по сути дублировать один и тот же код
повышается модифицируемость приложения
значительно сокращается объем кодирования
некоторые изменения мидели данных (M) вообще не затрагивают программную модель (O)
Откуда писать из сервиса или приложения совершенно нет какой либо разницы. У вас изменяется только источник. Источник на функционал кубика с записи в БД совершенно не влияет. Вы можете подавать на вход этого кубика параметры из разных источников. Хоть от сервиса, хоть от другого "кубика". Поэтому все мои рассуждения выше справедливы как для примера универсального сервиса, так для ваших специфических требований.
Реализуйте код, в котором складываются все параметры в HashMap, при необходимости выделите какие нибудь специфические параметры, если в этом есть необходимость и отдали все методу записи в БД
Сколько методов нужно для работы с БД в приложении? Всего ОДИН. С одним работать не удобно, параметров слишком много. Над этим одним методом нужно полтора десятка методов оберток, чтобы было удобно передавать параметры в разных сочетаниях и в разных структурах. А дальше "хоть вдоль, хоть поперек".
Как Вы готовите параметры для вызова этого ОДНОГО метода, совершенно не важно. В результате у Вас получается "слоеный пирог" вашего приложения, где каждый слой выполняет узкоспециализированную функцию.
Пришлось как то отвечать на требования смежников. Было множество однородных баз данных. В каждой БД множество схем таблиц предметной области. Мое приложение собирало виртуальную БД из этого множества БД. В один прекрасный момент было выдвинуто требование, что всё множество БД объединяется в ОДНУ БД в ЦОДе, а так как данных и изменений их очень-очень много смежники решили положить каждую базу в свой набор схем этой одной общей БД. Мне пришлось добавить всего один "кубик" между уже существовавшими "кубиками" примерно с 20 строками кода и модифицированное приложение успешно заработала с новыми требованиями (метод то всего один для работы с БД в коде).
Это частный случай - отсутствие поля name. Этот частный случай попадает под соглашение/требования программного слоя (в данном примере сервиса). Можно же составить соглашение, что должны передаваться только имена соответствующими полям БД? Можно. Можно составить соглашение что могут передаваться произвольные имена из заранее заданного списка и предусмотреть сопоставления передаваемых имен именам полей в таблицах БД. Можно. И не обязательно такое сопоставление нужно явно кодировать, его можно вынести в параметры приложения.
Естественно, сервер приложений "ходит" в БД под определенной учеткой со своими привилегиями в БД и эта учетка прописывается в конфигурации приложения. Как правило, это учетка имеет все привилегии на все таблицы предметной области сервера приложений. У сервера приложений как правило свой набор учетных записей пользователей, который в общем случае не пересекается с набором учеток в СУБД. Опять же не нужно валить все в кучу. Первый набор ограничивает доступ к объектам базы, второй набор ограничивает доступ к функционалу приложения (если в этом есть необходимость).
По поводу "установки значения в заказе статус PAID" - это внутренняя логика вашего приложения, устанавливаете как Вам удобно. Установили в кубике "запрос платежной системы" и передали в кубик "модификация модели данных". Не пойму ваших затруднений.
"Я вам уже объяснил - для многих людей ORM это и есть такое решение." - Это вовсе не значит, что это правильная трактовка технологии.
Последняя ваша реплика "список и названия полей в базе должны быть такие же, какие используются в SQL-запросах из приложения" - совсем не обязательно. SQL запрос может формироваться динамически, может быть определен в параметрах приложения. В SQL запросе могут быть не все поля таблицы.
Я же Вам ответил на вопрос секюрити - самый простой способ настроить секюрити в файле web.xml и программировать ничего не нужно вообще. Не устаивает web.xml реализуете Filter (другой кубик), если вам программировать больше нравиться. Не устаивает Filter - реализуйте любое другое удобное для Вас решение. Только не валите все в одну кучу.
Есть программная связь между моделью данных и программными объектами вашего приложения, что собственно и называется ORM, и логическая связь в предметной области. Вы, похоже, путаетесь в этих понятиях. То что Вы выделили термином "связанные" - это логическая связь.
Что Вы все время пытаетесь "скрестить ужа с ежом"? Зачем Вы пытаетесь решить все задачи в одном месте? Пример сервиса это "кубик" с узкой функциональностью. Он делает только то, что нужно ему делать - модифицировать любую модель данных без ORM или других подобных технологий. Все остальное должно делаться в других "кубиках" (программных слоях) вашего приложения. Секюрити - отдельный "кубик" (слой) приложения. Запрос платежного сервиса - отдельный "кубик". Делайте запрос в кубике "платежный сервис" и результат вызова при необходимости передавайте кубику "модификация модели данных". И тогда вопросов выше у Вас даже не возникнет.
И по поводу ORM. Как то узковато Вы понимаете, сводя это понятие к объекту (классу) HashMap<string, Object>.
Можно, ниже ссылка на универсальный сервис, который можно "повесить" на любою БД.
Да, в этом сервисе есть соглашения, в частости по URL. Но подобные соглашения есть и в любом вашем API.
По поводу "различий". Когда нет связи между моделью данных и программной моделью, то возможна ситуация при установке изменений, когда модель данных не соответствует серверу приложений. Чтобы не создавать пользователю "дискомфорт" с возможными ошибками или сообщениями (не обязательно, что они могут быть), то лучше все же сперва менять модель данных, а затем сервер приложений.
Это пример реализации универсального REST метода. На этой идее Вы можете реализовать подобный сервис под ваши потребности.
Что касается "по-вашему я должен предоставлять пользователю полный доступ к базе данных", то это совершенно другой вопрос, который можно решить по разному. Например, настроить в web.xml секции секюрити (можно настроить множества правил доступа вплоть до отдельно взятой таблицы) или усложнить код примера, добавив нужную функциональность по ограничению доступа.
Когда Вы связываете структуру данных и программную модель совершенно не важно каким способом с ORM или как то еще, то Вы объединяете два макро слоя ПО в один - уровень хранения и целостности данных с функциональным уровнем приложения. И таким способом значительно ухудшаете модифицируемость приложения, не говоря уже о том что нужно писать значительно больше кода, чем если бы Вы "решили задачу в общем виде".
Если Вы задаете такие вопросы "Как же тогда поменять данные в базе из программы, если они совсем не связаны? Вот добавили мы новое поле в таблицу, и что, там данные по волшебству появляться будут?", то и вы считаете что "в ORM модель данных и программная модель связаны".
Думаю, вашу логику, которую Вы описали выше, можно не реализовывать в вашем коде вообще. При работе с СУБД это можно выполнить на чистом SQL. В подавляющем числе случаев в своем коде я так и делаю.
Записываем (подготавливаем все для записи - это может быть ArrayList, Vector, массив) ваш JSON в БД. С этим справится и мой универсальный сервис. И дополняем SQL выражениями, которые и отработает вашу логику. И отдаем все на выполнение в одной транзакции.
Для этого нужно только слегка изменить код моего универсального сервиса, который добавить в подготовленный набор модификации базы требуемые SQL. Если эти SQL вынести еще в свойства приложения, то модифицируемость вашего приложения резко повысится. Вы можете часть новых требований отработать только изменениями SQL в свойствах приложения не затрагивая ваш код. Если учесть, что мой код "универсального" сервиса автоматически отработает любые изменения структуры JSON, если таковые возникнут, то вообще сказка получается.
Представляете, возникло требование - увеличить число полей в JSON, то Вы просто добавляете поля в таблицу/таблицы, в случае необходимости меняете SQL в свойствах - и все. Ваш код без каких либо правок работает с новыми требованиями.
Вы продолжаете мыслить реализацией класса Cart, отсюда и возникает у Вас вопрос как его куда то передать? Вы же где то у себя в коде его создали и заполнили его поля откуда то взятыми данными. Вот "откуда то" и нужно смотреть как это передать на сохранение.
Взгляните на свой класс Cart, CartItem и прочие подобные классы. Взгляните на код, который манипулирует этими классами. Не возникает мысли, что постоянно пишите один и тот же код, в котором отличаются по сути только используемыми именами классов и методов? Если не возникает, ну что ж пишите и дальше.
Так в чем проблема добавить какую то логику или ограничения? Нет проблемы. Если в вашем коде это реализовано, то почему Вы считаете, что подобную логику нельзя добавить в код моего примера? Я Вам показал идею, как можно уменьшить объем кодирования и повысить модифицируемость приложения. Хотите пользуйтесь, хотите нет. А уж какой логикой наполнить эту идею, извините, это уже ваша "головная боль". В своем же коде Вы это делаете по шаблону вашего движка, думаю и в моем варианте можете справиться.
В логике вашего приложения не ORM, а реализация ваших классов Cart, CartItem и всех прочих, которые являются некоторым представлением предметной области. Это представление можно реализовать каким то другим программным кодом и на его основе реализовать вашу логику. Можно? Можно.
Я понятие не имею какую логику вы хотите чтобы я реализовал. И возникает вопрос, зачем мне это нужно делать?
MAP классы - это то, что программно реализует соответствие одного другому. И если Вы эти классы не используете явно, то ваш движок, реализующий ORM, без них не будет работать.
Какая разница что это класс Person, Cart, CartItem или любой другой класс аналогичного назначения. Главное, что эту классу Person ставится в соответствие таблица Person, которая по количеству полей может 100% соответствовать полям класса Person. В этом корень проблемы !!! Т.е. Вам нужно для каждой таблицы и возможно представлению создавать собственный класс отображения. И совершенно не важно сгенерирован этот код по структуре таблицы или Вы его напишите в ручную. Этот код есть в вашем приложении.
Добавляете таблицу - добавляете новый класс.
Добавляете поле - добавляете новые методы в класс.
Добавили методы - корректируете другой код для вызова этих методов. Зачем? Если можно это не делать. И сразу куча плюсов. Меньше кода, легче модифицировать ПО, а при добавлении поля можно вообще код не модифицировать. Добавил поле, перезапустил приложения - красота.
Да какая разница в какое поле таблицы записывается какое именованное значение? Никакой. Я же Вам писал, что разработка ПО это прежде всего выработка соглашений. Вырабатываете соглашение, что имена значений должны совпадать. Отклонения от соглашения, например, прописали в конфиге приложения. Не нравится конфиг пропишите в коде на худой конец. Целую кучу кода Вам не лень писать, а небольшие отклонения которое отправит эту кучу кода в корзину в лом?
Хорошо, пусть будет источник данных или результат преобразования источника данных.
Хорошо, хешмапы так хешмапы. Если заметили, в моем примере входные данные в виде JSON или XML тоже преобразуются в хешмап, следовательно ваши данные моим "универсальным" кодом тоже успешно могут быть обработаны. Ни что не запрещает Вам в любом программном слое расширять полученный входной набор любыми другими дополнительными атрибутами, если в этом есть необходимость.
Логика приложения это отдельное преобразование входных данных. Еще один кубик/слой. Преобразованные в хешмап (в вашем понимании) входные данные передаются кубику "логика приложения", который либо возвращает модифицируемый хешмап, либо другую структуру программному слою "запись в БД". Все просто. Если Вам или кому то другому вдруг когда придется менять логику приложения, то нужно модифицировать или полностью заменить в коде только кубик.
Заблуждение. Вам это нужно только из-за того, что Вы используете фреймворк, который реализует идеологию ORM. Смените свой фреймворк.
Мне даже одной сточки писать не нужно. Много раз уже подчеркивал, мой пример будет работать с любой базой и модифицировать любые структуры в них. В том числе и с вашей. вашу логику в него добавить и можно полностью заменить ваше приложение.
ORM - Object Relational Model с моей точки зрения более точная расшифровка, чем Object Relational Mapping. Термин "mapping" Вас похоже и вводит в заблуждение. Даже ваша ссылка дает определение, в котором речь идет о реляционной модели данных и программной модели. Т.е. к различным MAP-классам термин ORM не имеет какого либо отношения.
По поводу "7-уровневой модели IP стека". Если теоретическая 7-уровневая модель на практике по каким то причинам реализуется в 6, 5, 4 - уровня, что это меняет? Главное что каждое ПО нужно пытаться разбить на уровни.
ORM мешает разбивать приложение на уровни, каждый из которых должен иметь узкую специализацию. ORM привел в качестве очень плохого решения.
Чем больше узкоспециализированных уровней в приложении, тем легче отвечать на самые неожиданные требования в процессе всего жизненного цикла этого приложения.
Данные, которыми Вам нужно манипулировать, откуда то же берутся? Берутся. Назовем это "источник данных". Какой именно "источник данных" совершенно не важно, это пользовать, сервис, событие или что то еще. У этого "источника данных" есть соглашения - имена и формат данных каждого поля? Есть. Если Вы в состоянии повлиять на это соглашения, то нужно составить соглашение таким образом, чтобы Вам было удобно с ними работать. Если не влияете, то можно подстроит свою модель данных в БД так, что так же с ними можно было удобно работать. Далее принимаете данные из "источника данных" и передаете их блоку/слою/кубику "манипулирование данных", который сохраняет результат в БД. Все просто. И совершенно не важно из какого источника данные получены и совершенно не важно какие манипуляции выполняются.
Из-за того что Вы не правильно понимаете идеологию ORM и возникает не понимание. Ваши классы Cart, CartItem и любые другие это программная (объектная) модель. Структура хранения данных в БД - это модель данных. ORM задает жесткую связь между двумя разными представлениями одной и той информации в разных макрослоях информационной системы, в частности в слое хранения данных и слое приложения - объект имеет отображение в модели. Это отображение фактически объединяет два совершенно разных макрослоя в одни (один без другого теряют какой либо смысл). Это очень плохо с точки зрения реализации и модифицируемости, писать кода надо много, вносить изменения тяжело.
В моем примере нет этой связи между моделью (БД) и объектами (программным кодом). Мой пример будет работать с любой базой. И еще раз подчеркиваю, ЭТО ПРИМЕР - который демонстрирует возможность работы без ORM. В этом примере используется программный слой манипулирования любыми данными (см поле database класса TableService). Этому программному слою все равно что выполнять, работать с одной таблицей или сразу во множеством.
Бизнес требования - это функциональные требования. Разные разработчики могут совершенно по разному преобразовать эти требования в программную модель приложения и структуры хранения. Так что это к обсуждаемой теме не относится.
В БД есть понятие метаданных, которые описывают всю структуру БД - таблицы, поля, типы, ключи и т.д. БД предоставляет API для получения этой информации. Не нужно гадать какая структура таблицы или какой PK этой таблицы. Можно спросить у БД, она ответит. И все. Необходимость программного описания (создание программных типов) отпадает. Обычно, при старте приложения идет опрос метаданных, по этим данным можно сразу или по мере необходимости генерировать SQL выражения. Смотри сразу сколько кода не нужно писать. И самое интересное, этот код можно использовать повторно в других проектах.
Мои доказательства опубликованы в GitHub-е - пример реализации универсального сервиса. Работает с любой БД и не нужно добавлять ни одной строчки кода. В вашем варианте нужно на любой чих писать "10 строк кода". Подчеркиваю НА ЛЮБОЙ. Причина - в том, что вашем коде заложена жесткая связь между моделью данных (предположу, что таблица CART) и программной моделью (классом CartItem). Класс CartItem 100% или с небольшими отличиями повторят структуру таблицы CART - это и есть ORM. При изменении таблицы CART вам нужно изменить класс CartItem или на оборот.
То что Вы считаете ORM таковым не является. Думаю, что и под виртуальной БД Вы понимаете не виртуальную БД.
У Вас эти "10 строк" применимы только в конкретном месте, в другом месте Вам нужно повторить эти "10 строк" и так везде, где Вы работаете с БД - постоянно повторяете один и тот же код с небольшими отличиями в основном в именах и специализированных типах данных (программной модели - O), которая должна соответствовать структуре таблиц (модели данных - М).
Иными словами - программная модель (O) соответствует (R) модели данных (M), что и называется ORM.
Если отказаться от использования ORM то
не нужно постоянно по сути дублировать один и тот же код
повышается модифицируемость приложения
значительно сокращается объем кодирования
некоторые изменения мидели данных (M) вообще не затрагивают программную модель (O)
Откуда писать из сервиса или приложения совершенно нет какой либо разницы. У вас изменяется только источник. Источник на функционал кубика с записи в БД совершенно не влияет. Вы можете подавать на вход этого кубика параметры из разных источников. Хоть от сервиса, хоть от другого "кубика". Поэтому все мои рассуждения выше справедливы как для примера универсального сервиса, так для ваших специфических требований.
Реализуйте код, в котором складываются все параметры в HashMap, при необходимости выделите какие нибудь специфические параметры, если в этом есть необходимость и отдали все методу записи в БД
Можно что то вроде
public void save(String tableName, String operation, HashMap parameters) {
...
}
и запишите все что угодно куда угодно
Но лучше еще добавить абстракции.
Сколько методов нужно для работы с БД в приложении? Всего ОДИН. С одним работать не удобно, параметров слишком много. Над этим одним методом нужно полтора десятка методов оберток, чтобы было удобно передавать параметры в разных сочетаниях и в разных структурах. А дальше "хоть вдоль, хоть поперек".
Как Вы готовите параметры для вызова этого ОДНОГО метода, совершенно не важно. В результате у Вас получается "слоеный пирог" вашего приложения, где каждый слой выполняет узкоспециализированную функцию.
Пришлось как то отвечать на требования смежников. Было множество однородных баз данных. В каждой БД множество схем таблиц предметной области. Мое приложение собирало виртуальную БД из этого множества БД. В один прекрасный момент было выдвинуто требование, что всё множество БД объединяется в ОДНУ БД в ЦОДе, а так как данных и изменений их очень-очень много смежники решили положить каждую базу в свой набор схем этой одной общей БД. Мне пришлось добавить всего один "кубик" между уже существовавшими "кубиками" примерно с 20 строками кода и модифицированное приложение успешно заработала с новыми требованиями (метод то всего один для работы с БД в коде).
В вашим подходом подобные задачи не решаемы.
Это частный случай - отсутствие поля name. Этот частный случай попадает под соглашение/требования программного слоя (в данном примере сервиса). Можно же составить соглашение, что должны передаваться только имена соответствующими полям БД? Можно. Можно составить соглашение что могут передаваться произвольные имена из заранее заданного списка и предусмотреть сопоставления передаваемых имен именам полей в таблицах БД. Можно. И не обязательно такое сопоставление нужно явно кодировать, его можно вынести в параметры приложения.
Естественно, сервер приложений "ходит" в БД под определенной учеткой со своими привилегиями в БД и эта учетка прописывается в конфигурации приложения. Как правило, это учетка имеет все привилегии на все таблицы предметной области сервера приложений. У сервера приложений как правило свой набор учетных записей пользователей, который в общем случае не пересекается с набором учеток в СУБД. Опять же не нужно валить все в кучу. Первый набор ограничивает доступ к объектам базы, второй набор ограничивает доступ к функционалу приложения (если в этом есть необходимость).
По поводу "установки значения в заказе статус PAID" - это внутренняя логика вашего приложения, устанавливаете как Вам удобно. Установили в кубике "запрос платежной системы" и передали в кубик "модификация модели данных". Не пойму ваших затруднений.
"Я вам уже объяснил - для многих людей ORM это и есть такое решение." - Это вовсе не значит, что это правильная трактовка технологии.
Последняя ваша реплика "список и названия полей в базе должны быть такие же, какие используются в SQL-запросах из приложения" - совсем не обязательно. SQL запрос может формироваться динамически, может быть определен в параметрах приложения. В SQL запросе могут быть не все поля таблицы.
Я же Вам ответил на вопрос секюрити - самый простой способ настроить секюрити в файле web.xml и программировать ничего не нужно вообще. Не устаивает web.xml реализуете Filter (другой кубик), если вам программировать больше нравиться. Не устаивает Filter - реализуйте любое другое удобное для Вас решение. Только не валите все в одну кучу.
Есть программная связь между моделью данных и программными объектами вашего приложения, что собственно и называется ORM, и логическая связь в предметной области. Вы, похоже, путаетесь в этих понятиях. То что Вы выделили термином "связанные" - это логическая связь.
Что Вы все время пытаетесь "скрестить ужа с ежом"? Зачем Вы пытаетесь решить все задачи в одном месте? Пример сервиса это "кубик" с узкой функциональностью. Он делает только то, что нужно ему делать - модифицировать любую модель данных без ORM или других подобных технологий. Все остальное должно делаться в других "кубиках" (программных слоях) вашего приложения. Секюрити - отдельный "кубик" (слой) приложения. Запрос платежного сервиса - отдельный "кубик". Делайте запрос в кубике "платежный сервис" и результат вызова при необходимости передавайте кубику "модификация модели данных". И тогда вопросов выше у Вас даже не возникнет.
И по поводу ORM. Как то узковато Вы понимаете, сводя это понятие к объекту (классу) HashMap<string, Object>.
Можно, ниже ссылка на универсальный сервис, который можно "повесить" на любою БД.
Да, в этом сервисе есть соглашения, в частости по URL. Но подобные соглашения есть и в любом вашем API.
По поводу "различий". Когда нет связи между моделью данных и программной моделью, то возможна ситуация при установке изменений, когда модель данных не соответствует серверу приложений. Чтобы не создавать пользователю "дискомфорт" с возможными ошибками или сообщениями (не обязательно, что они могут быть), то лучше все же сперва менять модель данных, а затем сервер приложений.
Это пример реализации универсального REST метода. На этой идее Вы можете реализовать подобный сервис под ваши потребности.
Что касается "по-вашему я должен предоставлять пользователю полный доступ к базе данных", то это совершенно другой вопрос, который можно решить по разному. Например, настроить в web.xml секции секюрити (можно настроить множества правил доступа вплоть до отдельно взятой таблицы) или усложнить код примера, добавив нужную функциональность по ограничению доступа.
Когда Вы связываете структуру данных и программную модель совершенно не важно каким способом с ORM или как то еще, то Вы объединяете два макро слоя ПО в один - уровень хранения и целостности данных с функциональным уровнем приложения. И таким способом значительно ухудшаете модифицируемость приложения, не говоря уже о том что нужно писать значительно больше кода, чем если бы Вы "решили задачу в общем виде".
Элементарно - https://github.com/java2ee/RestDB
Сервис может с ходу работать с любой БД
Если Вы задаете такие вопросы "Как же тогда поменять данные в базе из программы, если они совсем не связаны? Вот добавили мы новое поле в таблицу, и что, там данные по волшебству появляться будут?", то и вы считаете что "в ORM модель данных и программная модель связаны".