Pull to refresh

Comments 13

Мне больше нравится подход, когда база данных - такой же внешний сервис для нашего приложения, как и все другие. И тогда "классическая" ORM становится не нужна, нужен просто слой который правильно мапит доменные объекты в дтошки и правильно ими обменивается с базой. Hibernate в таком варианте использования приносит много дополнительной сложности

Если честно, то статья на сегодняшний день малоактуальна. За 20 лет много чего изменилось: появились быстрые мапперы, кодогенераторы, linq в том же c# давно обыденность. "Тяжелые" ORM сейчас, если и имеет смысл использовать, то только для небольших CRUD приложений.

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

Да вообще, оно, похоже - проблема не представления в виде объектов или в виде отношений между таблицами, а проблема кэширования.
Потому что если сделать, чтобы каждое изменение поля объекта немедленно в базу данных уходило и и при каждом чтении из базы данных читалось (т.е. при использовании настоящих, ничего не хранящих оберток вокруг данных в базе) - то описанные 'несоответствия между представлениями' в значительной мере исчезают. Ценой здоровенной просадки в производительности.

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

Оригинал ссылается на другой пост (в веб-архиве), в котором сначала идёт приличной протяженности описание событий Вьетнама и их последствий, затем связь Вьетнама с проблемами ORM, и затем идёт длинное и достаточно подробное описание конкретных проблем ORM (identity vs equivalence, inheritance и т.д.). Если я правильно понял, что имеется в виду под "не умеют объяснять, в чем проблема".

Есть статья (ссылка вытащено из википедии)

 затем идёт длинное и достаточно подробное описание конкретных проблем ORM

Которые ничего практически ничего не объясняют по поводу "А чего неудобно-то и где грабли?".
А должно было бы быть что то вроде:

Скрытый текст

Берем классическое "Заказ <-> позиции заказа" (на псевдо-sql)

TABLE Orders (
    order_id INT PRIMARY KEY,    
);
TABLE OrderItems (
    order_item_id INT PRIMARY KEY,
    order_id INT NOT NULL,
);

Вот что тут написано? Что OrderItem без Order не существует.
Теперь смотрим, как это в языке делается(условный ЯВУ):

order = new Order()
order_item = new OrederItem(данные поля); // Ой, OrderItem есть, но какого заказа?
order.add(order_item)

Если соответствовать схеме БД, одно должно делаться где-то как

order = new Order()
order_item = order.add();
order_item.fill(данные поля)

Все, несоответствие пропало. (Причем такое возможно - в Java при помощи тех же Inner Class. Но так делается далеко не всегда)
Причем первый способ - тоже можно без указанной накладки сделать.

TABLE Orders (
    order_id INT PRIMARY KEY,    
);
TABLE OrderItems (
    order_item_id INT PRIMARY KEY,
);
TABLE OrdeToItems(
    order_id INT NOT NULL,
    order_item_id INT NOT NULL
)

Тогда заказы, позиции и какая в каком - становятся отдельно, как и в ЯВУ, могут существовать отдельно и вкладывать одно в другое по мере необходимости.

Ну и так далее, по каждому пункту объяснений несоответствия должны быть примеры.

Ни одной статьи не видел.

Проблема кэша частично возникает из наличия транзакций и частично из наличия сущностей в памяти.

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

Наличие второго стейта в памяти приводит же к тому что выборки в бд могут его не учитывать. Тут орм тоже не виноват, а виновато как вы используете бд. Можно попытаться решить делая флаш изменений (то есть снова доп запросы) или перенося все чтения раньше чем происходит изменение (что далеко не всегда возможно). Решения на базе ручного маппинга будут так же этим страдать

Проблема кэша частично возникает из наличия транзакций и частично из наличия сущностей в памяти.

Нет, это понятно. Я про то что мне очень сильно кажется, что значительная часть проблем, которые причисляют к этому 'relational impedance mismatch' - оно не про этот mismatch, а именно проблемы кэширования.

Если скажем, если мы два раза запись по id вытащим - ORM нам должен один и тот же объект вернуть или копии?
Если один и тот же - сразу получаем проблемы совместного доступа к данным этого объекта. (Которая в базе данных тоже решается уже ее средствами. Причем 100% работать оно будет на так, как мы на уровне ЯВУ это делаем). Плюс, если приложение по кластеру размазано - то 'один и тот же' уже никак не получится.

Это все сложности, граблей и неудобства доставляет. Но непосредственно к модели данных оно отношения не имеет, это все про кэширование.

Если скажем, если мы два раза запись по id вытащим - ORM нам должен один и тот же объект вернуть или копии?

Зависит от ORM. Те, которые реализуют Identity Map (например, sqlalchemy) вернут один. Но только в случае использования одной "сессии". То есть ты сам управляешь где тебе нужно шарить объект, а где - нет.

То есть ты сам управляешь где тебе нужно шарить объект, а где - нет.

Ну вот, а операция индексирования контейнера (т.е. эквивалент поиска элемента по id-у) в ЯВУ практически всегда возвращает тот же самый объект (тот, что положили). Это подразумевается и как-то управляется не так чтобы часто. Если нужно копию - сам делай. Имеем несоответствия моделей данных и ожиданий для 'списка вещей' тут и 'списка вещей' там.

Но буква R из ORM тут причем? А ни при чем. Оно и с совершенно нереляционной базой так будет. Про это и мой тезис.

Ну погодите. Если вы ориентируетесь на конкурентнные транзакции, вы не можете шарить между ними инстансы, это приведет к нарушению изоляции. В питоне это решается тем что каждый объект "сессии" имеет внутри свой экземпляр IdM.

Да, R тут только при том, что для реализации связей надо внутри ORM отдельно приседать по сравнению с документными БД.

Да, R тут только при том, что для реализации связей надо внутри ORM отдельно приседать по сравнению с документными БД.

Так вот именно. Это понятие и пробемы с мапперами нужно старательно разделить на те, что действительно от  impedance mismatch и на те, что от всего остального. Ну и старательней описать, не рукомахательно-абстрактно, а с конкретными примерами "тут(тыкается пальцем в строки кода) мы мыслим и ожидам так, а вот тут(тыкается пальцем в другие строки кода) ожидаем эдак".
А оригинальную статью отправить в архивы.

ORM - лишний слой абстракции

нативный SQL позволяет точно контролировать какой запрос у тебя выполниться под капотом

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

Sign up to leave a comment.

Information

Website
t.me
Registered
Employees
11–30 employees