Ответ
JdbcTemplate — это утилита Spring Framework для работы с JDBC. Она работает на уровне SQL-запросов и результирующих наборов (ResultSet).
Criteria API — это часть спецификации JPA (Java Persistence API), предназначенная для типобезопасного программного построения запросов к объектной модели.
Сравнительная таблица:
| Критерий | JdbcTemplate (Spring JDBC) | Criteria API (JPA) |
|---|---|---|
| Уровень абстракции | Низкий, близок к SQL и реляционной модели. | Высокий, работает с объектами (ORM). |
| Типобезопасность | Отсутствует. Ошибки в SQL-строках или маппинге полей обнаруживаются во время выполнения. | Высокая. Запрос строится из метаданных классов-сущностей, ошибки часто выявляются на этапе компиляции. |
| Динамические запросы | Неудобно. Требуется конкатенация строк SQL, что подвержено ошибкам и SQL-инъекциям. | Идеально подходит. Запрос строится программно через объекты CriteriaBuilder и CriteriaQuery. |
| Пример | Работа с SQL и ручной маппинг: | Программное построение запроса к сущности: |
// JdbcTemplate: SQL-строка, параметры, RowMapper
String sql = "SELECT * FROM user WHERE age > ?";
List<User> users = jdbcTemplate.query(sql,
(rs, n) -> new User(rs.getString("name"), rs.getInt("age")),
minAge);
// Criteria API: типобезопасное построение
CriteriaBuilder cb = entityManager.getCriteriaBuilder();
CriteriaQuery<User> cq = cb.createQuery(User.class);
Root<User> user = cq.from(User.class);
cq.select(user).where(cb.gt(user.get("age"), minAge));
List<User> users = entityManager.createQuery(cq).getResultList();
| Использование | Прямые или сложные нативные SQL-запросы, высокая производительность, легаси-системы без JPA. | Сложные, динамические запросы в приложениях, использующих JPA/Hibernate, где важна типобезопасность и поддержка. |
Вывод: JdbcTemplate — это улучшенный JDBC для SQL-центричного доступа. Criteria API — это инструмент JPA для объектно-ориентированного, безопасного построения запросов.
Ответ 18+ 🔞
Слушай, а вот это реально интересный вопрос, который многих вводит в ступор. Представь себе двух работяг на стройке запросов к базе. Один — это JdbcTemplate, такой себе мастер-лоботряс с паяльником, который вручную паяет каждую жилку SQL-провода. Второй — Criteria API, этакий архитектор-зануда с чертежами, который всё пытается построить из типобезопасного конструктора «Лего», чтобы ни один болтик не потерялся.
JdbcTemplate — это, по сути, прокачанный качком старый добрый JDBC. Spring его обнял, причесал, закрыл ему все эти ужасные try-catch-finally на ресурсы, но суть осталась: ты пишешь SQL-строку, как в каменном веке, и сам, блядь, разбираешь, что тебе вернулось. Это низкоуровневый доступ, близкий к железу (то есть к базе). Быстро? Да, овердохуища быстро. Гибко? Абсолютно, можешь любой запрос, даже тот, от которого сам PostgreSQL охренеет. Но безопасно? Ну, как сказать… Если забудешь ? и вставишь параметр напрямую — привет, SQL-инъекция, твоя компания накрылась медным тазом.
Criteria API — это уже другая, высокая материя. Это часть JPA, то есть объектного мира. Ты тут не со строками работаешь, а с классами-сущностями, их полями и связями. Хочешь динамический запрос собрать? Пожалуйста: бери CriteriaBuilder и строй, как из кубиков. Компилятор тебя за руку схватит, если ты попытаешься обратиться к полю user.get("aggeeee") — такого поля нет, и он тебе сразу: «Чувак, бля, опечатка, иди исправляй». Это главный козырь — типобезопасность. Ошибки ловятся на этапе компиляции, а не в проде в три часа ночи.
А теперь смотри, как они в деле выглядят:
JdbcTemplate — тут всё честно, по-пацански. Написал запрос, подставил параметры, сам распарсил результат.
// Видишь эту строку? Это мина замедленного действия, если её неправильно собрать.
String sql = "SELECT * FROM user WHERE age > ?";
List<User> users = jdbcTemplate.query(sql,
// А это ручной маппинг. Ошибись в названии колонки — получишь null и пиздец в логике.
(rs, n) -> new User(rs.getString("name"), rs.getInt("age")),
minAge);
Criteria API — тут уже интеллигентская возня. Никаких строк, только объекты и методы.
// Достаём наш «станок» для сборки запросов
CriteriaBuilder cb = entityManager.getCriteriaBuilder();
// Говорим, что будем варить суп из User
CriteriaQuery<User> cq = cb.createQuery(User.class);
Root<User> user = cq.from(User.class);
// Собираем условие: где возраст больше minAge. `get("age")` — это ссылка на поле класса!
cq.select(user).where(cb.gt(user.get("age"), minAge));
// Запускаем
List<User> users = entityManager.createQuery(cq).getResultList();
Короче, итог простой, как три копейки:
- Берёшь JdbcTemplate, когда: «Надо быстро, надо нативно, запрос хуёво-сложный, или JPA тут вообще не ночевала». Легаси система, кастомная аналитика, хардкорная оптимизация — его стезя.
- Берёшь Criteria API, когда: «Проект на Spring Data JPA, а запрос надо собрать динамически, да так, чтобы компилятор меня прикрыл». Сложные фильтры, поиски, построители отчётов — его царство.
Выбор, как всегда, зависит от задачи. Можно гвоздь микроскопом забить (JPA для простого SELECT *), а можно и скальпелем доску пилить (JdbcTemplate для всей бизнес-логики). Но когда знаешь разницу — уже не облажаешься.