Ответ
Нативный запрос в Hibernate — это обычный SQL-запрос, который выполняется напрямую в базе данных, минуя HQL/JPQL и часть механизмов ORM (например, автоматическую выборку по связям).
Как создать нативный запрос:
// Создание запроса с явным указанием класса сущности для маппинга результата
List<User> users = session.createNativeQuery(
"SELECT * FROM users WHERE department_id = :deptId",
User.class)
.setParameter("deptId", 5)
.getResultList();
// Для сложных или нестандартных результатов используется ResultSetMapping
List<Object[]> results = session.createNativeQuery(
"SELECT u.name, COUNT(o.id) FROM users u LEFT JOIN orders o ON u.id = o.user_id GROUP BY u.id")
.getResultList();
Когда использовать нативный запрос:
✅ Сложные аналитические запросы с оконными функциями, сложными GROUP BY.
✅ Вызов хранимых процедур или специфичных функций СУБД.
✅ Критичные к производительности операции, где оптимизированный вручную SQL дает значительный выигрыш.
✅ Работа с legacy-схемами, которые сложно или невозможно идеально отобразить на сущности.
Риски и ограничения:
❌ Потеря переносимости: Запрос привязан к синтаксису конкретной СУБД.
❌ Риск SQL-инъекций: Всегда используй параметризованные запросы (как в примере с :deptId).
❌ Обход кэша Hibernate: Может привести к несогласованности данных.
❌ Ручной маппинг: Часто требуется дополнительная работа по преобразованию ResultSet в объекты.
Ответ 18+ 🔞
Вот, смотри, как обстоят дела с этими вашими нативными запросами в Hibernate. Представь, что Hibernate — это такой заботливый, но слегка занудный переводчик. Он всё хочет перевести на свой HQL/JPQL, чтобы было красиво и независимо от базы данных. А иногда тебе надо просто крикнуть: «Отъебись, я сам знаю, как сказать!» Вот это и есть нативный запрос — чистый, голый SQL, который ты суёшь прямиком в базу, минуя все эти философские размышления фреймворка.
Как это, блядь, делается:
// Самый простой случай: говоришь — вот SQL, вот класс сущности, мапь, сука, обратно в объекты.
List<User> users = session.createNativeQuery(
"SELECT * FROM users WHERE department_id = :deptId",
User.class)
.setParameter("deptId", 5) // Смотри, параметры! Без них ты — говнокодер, открывающий дверь SQL-инъекциям.
.getResultList();
// А вот когда результат — какая-то ебеня из нескольких колонок или агрегатов.
// Тут уже Hibernate руками разводит: «Ой, а это во что мапить-то?».
// И приходится брать голый Object[] и самому ковыряться.
List<Object[]> results = session.createNativeQuery(
"SELECT u.name, COUNT(o.id) FROM users u LEFT JOIN orders o ON u.id = o.user_id GROUP BY u.id")
.getResultList();
Так когда же надо выёбываться и писать SQL самому?
✅ Когда запрос сложнее, чем твои жизненные проблемы. Оконные функции, хитрые GROUP BY, которые на HQL выглядят как попытка объяснить квантовую физику мартышке.
✅ Надо дернуть хранимую процедуру или какую-нибудь специфичную функцию базы вроде GEOGRAPHY_ПОШЛО_ВСЁ_НАХУЙ. ORM такое часто не умеет.
✅ Перформанс ебёт твою мать. Иногда, посмотрев на план запроса, который сгенерил Hibernate, хочется плакать. А твой ручной, отполированный запрос летает.
✅ Работаешь с легаси-схемой, которую проектировал пидарас шерстяной. Таблицы TBL_123_USR_A, колонки USR_NM_VC, связи через три левых джойна по дате. Мапить это на сущности — тот ещё геморрой. Проще написать SQL и забыть.
Но предупреждаю, тут подводных ебуч везде овердохуища:
❌ Прощай, переносимость! Написал кучу SQL под PostgreSQL? Попробуй запустить это на Oracle. Правильно, получишь Syntax error, идиот. Придётся переписывать.
❌ SQL-инъекции — это пиздец. Я не шучу. Если ты вставляешь значения в строку через конкатенацию ("WHERE name = '" + name + "'"), то ты — манда с ушами, и твой сервис скоро будут использовать для майнинга крипты. Всегда. Используй. Параметры. Как в примере выше.
❌ Кэш Hibernate может нихуя не понять. Ты проапдейтил данные напрямую в базе нативным запросом, а Hibernate тебе из своего кэша старые значения подсовывает. Волнение ебать, отладка на три часа.
❌ Маппинг — твоя головная боль. Hibernate за тебя связные сущности (User.orders) не подтянет. Получил голые колонки — сам парсь, сам создавай объекты. Самый весёлый цирк начинается, когда структура результата не совпадает ни с одной сущностью.
Короче, инструмент мощный, но как бензопила — в руках идиота оставит от проекта рваные ошмётки. Используй с умом, только когда ORM реально не справляется или когда оптимизация — вопрос жизни и смерти. А так — живи спокойно, пусть Hibernate сам всё транслирует, это обычно надёжнее.