сеньорчикОткрыть в Telegram
← все вопросывопросы для собеседований · Spring и Hibernate

Вопросы по Spring и Hibernate на собеседовании

Spring спрашивают почти на каждом собесе Java-разработчика, и именно здесь чаще всего выясняется, что человек писал аннотации, не понимая, что за ними происходит. Транзакции и ленивая загрузка дают самый честный срез.

162 вопросов в банке·10 подтем·ниже разбор 9

Что спрашивают

Из чего состоит тема

Так тема разложена в тренажёре: движок ведёт прогресс по каждой подтеме отдельно и возвращает те, где вы ошибаетесь.

Разборы подтем

Конспект по каждой: что это, как отвечать вслух, на чём валятся, плюс вопросы для самопроверки.

Примеры вопросов с разбором

  1. #caching1 / 9
    Что такое кэш первого уровня (L1) в Hibernate?
    A)Кэш в пределах одной сессии — всегда включён, гарантирует идентичность сущностей
    B)Общий для всех сессий и потоков кэш, который надо явно включать через отдельный провайдер вроде Ehcache
    C)Кэш скомпилированных SQL-запросов, переиспользуемый между разными приложениями на одном сервере БД
    D)Дисковый кэш, куда Hibernate сбрасывает загруженные сущности, чтобы пережить перезапуск приложения
    показать ответ и разбор
    +A)Кэш в пределах одной сессии — всегда включён, гарантирует идентичность сущностей

    // разбор: Кэш ПЕРВОГО уровня (L1) — это и есть контекст персистентности (Session/EntityManager): он ВСЕГДА включён, его нельзя отключить, и он локален для ОДНОЙ сессии/единицы работы. В нём хранятся все managed-сущности, поэтому повторный find по тому же id в этой сессии не идёт в БД и возвращает тот же объект. При закрытии сессии L1 очищается. Это не разделяемый и не настраиваемый кэш — им управляет сам Hibernate в пределах транзакции. Настраиваемый разделяемый кэш — это уже L2.

  2. #entity_lifecycle2 / 9
    Какие состояния жизненного цикла бывают у сущности JPA?
    A)Transient, Persistent (managed), Detached, Removed
    B)Created, Running, Paused, Stopped — как у обычного потока исполнения в многопоточном приложении
    C)Draft, Published, Archived — соответствующие стадиям публикации записи в базе данных приложения
    D)Open, Closed, Committed, RolledBack — состояния, наследуемые сущностью от текущей транзакции
    показать ответ и разбор
    +A)Transient, Persistent (managed), Detached, Removed

    // разбор: Сущность проходит четыре состояния: TRANSIENT — только что создана через new, у неё нет id и контекст её не отслеживает; PERSISTENT/managed — привязана к контексту персистентности (EntityManager), Hibernate отслеживает её изменения и синхронизирует с БД; DETACHED — была persistent, но контекст закрылся (или её выселили) — изменения больше не отслеживаются; REMOVED — помечена на удаление. Переходы: persist (transient→persistent), remove (→removed), закрытие сессии (persistent→detached), merge (detached→managed-копия). Понимание состояний объясняет, почему изменения то сохраняются сами, то нет.

  3. #fetching_nplus13 / 9
    Чем LAZY-загрузка связи отличается от EAGER?
    A)LAZY грузит связь при первом обращении; EAGER — сразу вместе с сущностью
    B)LAZY загружает связанные данные только из кэша, а EAGER — напрямую из базы данных заново
    C)LAZY и EAGER отличаются лишь порядком колонок в SELECT, но обе грузят связь одним запросом
    D)EAGER откладывает загрузку до обращения, а LAZY подгружает всё содержимое связи заранее при чтении
    показать ответ и разбор
    +A)LAZY грузит связь при первом обращении; EAGER — сразу вместе с сущностью

    // разбор: LAZY: связь не грузится вместе с сущностью — вместо неё стоит прокси/обёртка, а реальный SELECT выполняется при ПЕРВОМ обращении к связи (если сессия ещё открыта). EAGER: связь подгружается СРАЗУ при загрузке корневой сущности (обычно джойном или отдельным запросом). LAZY экономит, когда связь не нужна, но рискует LazyInitializationException (доступ после закрытия сессии) и N+1 (в цикле). EAGER гарантирует наличие данных, но тянет лишнее и провоцирует избыточные запросы. Обычно ставят LAZY и подгружают что нужно явно (JOIN FETCH).

  4. #orm_mapping4 / 9
    Что такое ORM (например, Hibernate)?
    A)Отображение объектов на строки таблиц — работа с БД через объекты, а не SQL
    B)Отдельная база данных, встроенная в приложение, которая заменяет собой внешнюю СУБД
    C)Инструмент, который автоматически проектирует схему базы данных по требованиям бизнес-аналитика
    D)Протокол сетевого обмена между приложением и базой данных вместо стандартного драйвера JDBC
    показать ответ и разбор
    +A)Отображение объектов на строки таблиц — работа с БД через объекты, а не SQL

    // разбор: ORM (Object-Relational Mapping) — прослойка, отображающая объекты приложения на строки реляционных таблиц: класс ↔ таблица, поле ↔ колонка, связь между объектами ↔ внешний ключ. Разработчик работает с СУЩНОСТЯМИ и их графами, а ORM сам генерирует SQL (SELECT/INSERT/UPDATE/DELETE), управляет идентичностью объектов, кэшем и транзакциями. Hibernate — самая популярная реализация спецификации JPA. Плюсы — меньше шаблонного JDBC; риски — скрытые запросы (N+1), утечки абстракции (нужно понимать, какой SQL порождается).

  5. #transactions_locking5 / 9
    Что такое оптимистичная блокировка (@Version) в JPA?
    A)Поле-версия проверяется при UPDATE; конфликт параллельной правки → OptimisticLockException
    B)Блокировка строки в БД на всё время транзакции, из-за которой другие транзакции ждут её завершения
    C)Механизм, который оптимистично предполагает отсутствие ошибок и отключает проверки на конфликты
    D)Кэш версий сущностей в памяти, ускоряющий чтение за счёт хранения нескольких копий одной строки
    показать ответ и разбор
    +A)Поле-версия проверяется при UPDATE; конфликт параллельной правки → OptimisticLockException

    // разбор: Оптимистичная блокировка НЕ держит строку заблокированной: она добавляет сущности поле @Version (int/long/timestamp). При UPDATE Hibernate включает в WHERE проверку версии (... WHERE id=? AND version=?) и инкрементирует её. Если между чтением и записью КТО-ТО другой уже изменил строку (версия не совпала — 0 обновлённых строк), бросается OptimisticLockException — «кто-то опередил, перечитай и повтори». Подходит для сценариев с редкими конфликтами (веб-формы): не блокирует конкурентов, а обнаруживает конфликт по факту. Дёшево и хорошо масштабируется.

  6. #bean_lifecycle_scopes6 / 9
    Какой скоуп у бина Spring по умолчанию?
    A)singleton — один экземпляр на контейнер
    B)Prototype — новый экземпляр создаётся при каждом внедрении и обращении к бину из контейнера
    C)Request — по одному экземпляру бина на каждый входящий HTTP-запрос к приложению
    D)Thread — отдельный экземпляр бина для каждого потока, обращающегося к контейнеру за ним
    показать ответ и разбор
    +A)singleton — один экземпляр на контейнер

    // разбор: По умолчанию бины — SINGLETON: контейнер создаёт ОДИН экземпляр и отдаёт его всем, кто его запрашивает/внедряет (один на контейнер, не обязательно на всю JVM). Другие скоупы: prototype (новый объект на каждое получение), а в вебе — request, session, application. Важное следствие singleton: общий экземпляр разделяется потоками, поэтому хранить в нём изменяемое состояние небезопасно (см. потокобезопасность). Скоуп задаётся @Scope.

  7. #ioc_di7 / 9
    Что такое инверсия управления (IoC) в Spring?
    A)Создание и связывание объектов берёт на себя контейнер, а не сам код
    B)Автоматическое обращение порядка выполнения методов класса на противоположный при старте контейнера
    C)Механизм, при котором каждый объект сам создаёт все свои зависимости через оператор new внутри себя
    D)Способ инвертировать наследование: родитель начинает зависеть от своих потомков, а не наоборот
    показать ответ и разбор
    +A)Создание и связывание объектов берёт на себя контейнер, а не сам код

    // разбор: Инверсия управления — принцип, при котором управление созданием объектов и их зависимостями передаётся ВНЕШНЕМУ контейнеру (Spring), а не пишется руками через new внутри классов. Контейнер сам инстанцирует бины, внедряет их зависимости (DI — конкретная реализация IoC) и управляет жизненным циклом. Класс лишь ОБЪЯВЛЯЕТ, что ему нужно, и получает готовое. Это снижает связанность, упрощает подмену реализаций и тестирование (можно внедрить мок).

  8. #spring_boot_aop8 / 9
    Что делает автоконфигурация (auto-configuration) Spring Boot?
    A)Сама настраивает бины по наличию зависимостей в classpath и свойств
    B)Автоматически пишет исходный код приложения по описанию требований и компилирует его при старте
    C)Отключает всю ручную конфигурацию: в Spring Boot не получится переопределять создаваемые бины вручную
    D)Раздаёт приложение по нескольким серверам, автоматически масштабируя его под текущую нагрузку
    показать ответ и разбор
    +A)Сама настраивает бины по наличию зависимостей в classpath и свойств

    // разбор: Автоконфигурация — сердце «магии» Boot: по тому, что ЕСТЬ в classpath (стартеры-зависимости) и в свойствах, Boot САМ создаёт разумные бины по умолчанию — увидел spring-boot-starter-data-jpa и драйвер БД → настроил DataSource, EntityManager, транзакции. Реализовано через @Conditional-условия (@ConditionalOnClass/OnMissingBean/OnProperty). Ключевой принцип: ваши собственные бины и свойства ПЕРЕОПРЕДЕЛЯЮТ дефолты (автоконфиг «отступает», если бин уже задан). Так убирают тонны шаблонной XML/Java-конфигурации.

  9. #spring_data_tx9 / 9
    Как в Spring Data JPA создать запрос findByEmail(String email)?
    A)Объявить метод в интерфейсе-репозитории — Spring сгенерирует реализацию по имени
    B)Написать полную реализацию метода с JDBC-кодом вручную в классе, реализующем интерфейс репозитория
    C)Создать хранимую процедуру в базе данных с именем findByEmail и вызвать её напрямую из кода
    D)Скопировать SQL-запрос в отдельный XML-файл маппинга, который Spring загрузит по имени метода
    показать ответ и разбор
    +A)Объявить метод в интерфейсе-репозитории — Spring сгенерирует реализацию по имени

    // разбор: Spring Data JPA генерирует реализацию репозитория из ИНТЕРФЕЙСА: достаточно объявить метод по соглашению об именовании (findByEmail, findByAgeGreaterThan, findByLastNameOrderByFirstName), и Spring разберёт имя и построит JPQL/запрос сам — без кода. Для сложных запросов есть @Query (JPQL или nativeQuery), Specification/Criteria, QueryDSL. Базовый CrudRepository/JpaRepository уже даёт save/findById/findAll/delete. Это резко сокращает шаблонный DAO-код. Слишком длинные производные имена — сигнал перейти на @Query.

это 9 из 162

Ещё 153 вопросов по теме — в тренажёре, с движком повторения

Прочитать разбор и ответить самому — разные навыки. В Сеньорчике вопросы идут сессиями, а движок возвращает подтемы, где вы ошибаетесь, пока они не начнут отскакивать. Бесплатно, лимит по энергии.

Частые вопросы