Какие способы взаимодействия Java приложений с базами данных существуют
Что проверяют
Знаете ли вы уровни абстракции над базой и умеете ли выбирать между ними осознанно. За вопросом обычно стоит проверка, понимаете ли вы, какой SQL порождает ваш код. Уточняющий вопрос почти гарантирован: N+1 запросов, транзакции или как вы это тестируете.
Как отвечать
Идите снизу вверх, от голого API к фреймворкам:
- JDBC: базовый стандарт,
DataSource,PreparedStatement,ResultSet, пакетная отправка черезaddBatchиexecuteBatch. В проде всегда за пулом соединений, де-факто стандарт это HikariCP; - Spring JDBC:
JdbcTemplateи более новыйJdbcClient(Spring Framework 6.1 и выше) с цепочечным API и именованными параметрами, без бойлерплейта, но SQL пишете вы; - JPA и Hibernate: Jakarta Persistence, персистентный контекст как кеш первого уровня, автоматическое отслеживание изменений, ленивые связи. Spring Data JPA сверху генерирует репозитории по именам методов и понимает
@Query; - jOOQ: типобезопасный SQL из модели, сгенерированной по схеме. Опечатка в имени колонки становится ошибкой компиляции;
- Spring Data JDBC и MyBatis: середина, работа с объектами без персистентного контекста и ленивых связей;
- R2DBC: неблокирующий доступ для реактивного стека. С виртуальными потоками начиная с Java 21 его ниша сузилась: обычный JDBC больше не занимает несущий поток.
Обязательно упомяните обвязку: миграции схемы через Flyway или Liquibase, @Transactional и уровни изоляции, оптимистичную блокировку по @Version, Testcontainers для тестов на настоящей СУБД вместо H2, которая ведёт себя иначе.
Где спотыкаются
Не могут объяснить N+1. Это первый вопрос вдогонку, и ответ должен включать join fetch, @EntityGraph или батч-фетчинг, а не «увеличим кеш».
Думают, что @Transactional работает при вызове метода из того же класса. Прокси в этом случае обходится стороной, и транзакции просто нет.
Собирают SQL конкатенацией строк. Это и SQL-инъекция, и потеря переиспользования плана запроса на стороне базы.