Расскажите про опыт работы с ORM и мапперами
Что проверяют
Понимаете ли вы, что скрывает ORM, и умеете ли выходить за её пределы.
Как отвечать
Разложите на три уровня.
Что использовали: JPA с Hibernate как основной способ, Spring Data поверх него для генерации репозиториев, а для сложных запросов прямой SQL через шаблон запросов или типобезопасный построитель.
Что понимаете внутри, это главное:
- контекст персистентности и грязная проверка: загруженная сущность отслеживается, и изменение поля само превращается в обновление при сбросе. Явный вызов сохранения не нужен, и это первое, что удивляет новичков;
- состояния сущности: новая, управляемая, отсоединённая, удалённая;
- ленивая загрузка и её обратная сторона: обращение к связи вне транзакции даёт исключение;
- проблема N+1: сто сущностей превращаются в сто первый запрос. Лечится соединением с загрузкой, графом сущностей или пакетной догрузкой.
Что делали руками: включали показ генерируемого SQL и счётчик запросов, добавляли проверку числа запросов в тесты как защиту от возврата проблемы, переписывали тяжёлые места на прямые запросы, настраивали пакетную вставку.
Про мапперы между слоями скажите отдельно: наружу отдаются не сущности, а объекты передачи данных. Причин две: сериализация сущности тянет ленивые связи и порождает лавину запросов, а внутренняя модель не должна быть публичным контрактом. Преобразование делают вручную либо генератором вроде MapStruct, который создаёт код на этапе компиляции и потому не стоит ничего во время выполнения. Мапперы на рефлексии медленнее и ошибки в них всплывают только в рантайме.
Честный вывод, который стоит произнести: ORM не освобождает от знания SQL, а требует его. Без понимания генерируемых запросов она превращается из ускорителя в источник проблем.
Где спотыкаются
Никогда не смотрят на сгенерированный SQL.
Отдают сущности прямо из контроллера.
Ставят везде жадную загрузку, чтобы убрать исключение.
Делают массовые операции через сущности вместо одного запроса.