Як тільки з’явився JPA, перехід між різними ORM-технологіями ставав
простішим... Але конкуренти є (EclipseLink, DataNucleus, Apache OpenJPA).
Цікаво, як багато розробників робили цей перехід і навіщо? Особисто я за свою скромну кар’єру бачив конкурента лише один раз і те, згодом перейшли на Hibernate.
В JPA три анотації є обов’язковими для сутності (@Table, @Entity, @Id). Крім того, Hibernate вимагає гетери/сеттери і дефолтний конструктор
@Table не є обов’язковою анотацією. Крім того, Hibernate не вимагає гетери/сетери... мені не вдалося швидко загуглити з якої саме версії, але про переваги field access питали ще в
Також не зрозумілі натяки на
20-річний шлейф помилок та недолiкiв Hibernate
У Hibernate були певні складнощі, якщо наша сутність була immutable (read-only).
але повернемось до сабжу.
Якщо не потрібен ORM від слова Object, а вигідніше працювати з plain SQL і POJO/record, то є «старий» Spring JDBC і, наприклад, MyBatis, які дійсно
просто дозволяють простіше використовувати JDBC.
Spring Data JDBC по суті робить те саме, але оманливо схожий на JPA завдяки @Table, @Column, CrudRepository (але суть зовсім інша) і натомість пропонує таку кілер-фічу?!
Немає i lazy loading. Усі асоціації відразу завантажуються під час завантаження основного об’єкта (Aggregate Root). Відповідно, коли ви зберігаєте об’єкт, автоматично зберігаються і всі асоціації (навіть якщо вони не змінювалися). Це може призвести до деяких проблем з performance, якщо у вас є досить багато зв’язків.
Добре, що ви вказуєте на це і підтверджуєте вимірами N+1 проблему.
Обычно — inject-ить mock-и перечисленных объектов, проверять вызовы методов.
Я прошу посмотреть — глазами на ноутбуке, не доступ к репозиторию — код проекта. Кто-то сильно напрягается NDA, как будто у меня в пуговице шпионская камера, кто-то показывает — и тогда становится яснее, насколько сопромат на собеседовании коррелирует с реальным положением дел.
Спасибо за комментарий.
А теперь представьте что DB всё-таки есть, и её охраняют 3 опасных DBA.
Как везти разработку в таких условиях?
Прочитал вопрос как «Что делать, если схема БД уже создана?» Два варианта: возможно Hibernate не нужен вообще, см. MyBatis. Либо JPA и «дизассемблировать» таблицы, большое количество полей «сгруппировать» с помощью @Embeddable, использовать enum и т.д.
ваше виденье inheritance
Я не сторонник использования наследования, это специфичный приём и должен применять аккуратно, вот моя старая, несколько наивная статья dou.ua/...n-vs-inheritance-in-java
Если наследование всё таки нужно, и проектировать от Java, то Hibernate прекрасно его поддерживает и предоставляет три стратегии для этого.
Если «дизассемблировать» таблицы, то @MappedSuperClass для повторяющихся полей (например, в каждой таблице есть аудит createdBy, createdAt, modifiedBy, modifiedAt) мне не кажется хорошей идеей. Я предолжил бы использовать композицию и @Embeddable.
В итоге получается что простой код легко менять и поддерживать в не зависимости от того есть тесты или нет.
Странное утверждение. Как можно «легко менять и поддерживать» без тестов?!
Пример выше — простой, но плохой код.
инструменты мутационного тестирования
Статья же про качественный код? Имхо, если мутационное тестирование нужно, вряд ли это хороший код.
Не всегда.
Классический пример. Простой и понятный код, только нетестируемый и поэтому с багом.
public void congrats() { Date today = new Date(); if (today.getMonth() == 1 && today.getDay() == 1) { System.out.println("Happy New Year!"); } }
Тут нюанс. Вызов метода может быть весьма простым. И это может быть ок для внешних consumer-ов, пока не придётся править его бизнес-логику.
Если на метод сложно написать тест — код не очень.
Прямо под вашим комментарием другое мнение. В теме поста диаграмма базы и ддл для неё. Что скажете? Какие классы предложите?
У в предметной области нет другого поведения кроме как круд
Эээ... Вроде как само определение «предметная область» подразумевает, что там поведение есть, если мы не совсем про записную книжку говорим.
P.S. ORM considered harmful
Без задачи такое утверждать некорректно.
Как можно «подбирать» классы под базу?! Это же телега впереди лошади!
Так делают, в совсем тяжелых случаях 1:1. Тяжело работать в таких проектах, когда все дао, сервисы и т.д. уже написаны.
Так вот, итоги.
А таки что ви имеете пготив сегвисов?
Таки имею. Что мой, что ваш сервисы — процедуры.
ООП как раз тут и нет почти
... и поэтому на них нет юнит-тестов, сразу интеграционные.
Не хотите? Добро пожаловать в мою модель.
Я наконец-то понял о чём мы спорим. Это ORM vs Native SQLИнтенсивный JPQL, где на стороне ORM в плюсах полная свобода в модели и отсутсвие sql, когда можно просто пройтись по ней (что я и демонстрирую с помощью Entity->RRO). Только в случае Native SQL (+MyBatis) преимущество легче продемонстировать на каком-то аналитическом запросе, где ORM «вытянет несколько мегабайт данных» (цитата из другого топика), то c JPQL это невозможно неочевидно.
Мне кажется, пока вы ограничены JPQL, в N+1 выиграть сложно, максимум паритет, и то за счёт написания запросов руками.
Вы ближе ко второму подходу, поэтому пишите JPQL, накладываете ограничения (нет би-дирекшнл связям, иерархия и т.д.), но от вытягивания графа с помощью Hibernate.initialize() не отказываетесь.
Вам не кажется эта структура офигеть каким искусственным, громоздким, излишним, error-prone и вообще неудачным решением?
Извините, не удержался :-)
Не то чтобы я явной благодарности прошу, скорее просто какой-то реакции, но, кажется, для интенсивного jpql вам нужен QueryDSL.
Кстати, да. Как иммутабельность с коллекциями-то?
Со скалой, увы, не знаком. Поэтому на snapeless/slick только попробую посмотреть. Добавил DDL в пост, если покажете, как оно на скале, буду дополнительно благодарен.
Покажите, пожалуйста. Добавил DDL схемы в пост.
Давайте переформулируем. Да, у меня круд. Это проблема?
А если БД уже есть?
Почему? Необязательно ведь Хибернейту DDL в базу разрешать, но можно же взять сгенеренную схему в скрипт flyway.
У меня есть небольшой опыт работы с Hibernate (см. статью). Я понимаю, как по классам строятся таблицы — это делает фреймворк. Я спрашиваю, как угадать классы по таблицам.
Такое ощущение, что публика предпочитает читать POJOs из таблиц, Unit of Work — это слишком сложно? непривычно? хотя, казалось бы, должно быть обратно, а Spring попустительствует этому подходу. Всё равно Lazy initialization exception затыкают EAGER-ом, так давайте из коробки сделаем
дескать ресурсы сейчас дешёвые.