Ответ вслух Middle Spring Data JPA обновлено

Как работает save в Spring Data JPA

Вопрос

Что происходит при вызове repository.save()? Когда он лишний и какие с ним бывают сюрпризы?

Попробуйте сами

Ответьте вслух за 2 минуты, как на собесе. Потом сверьтесь с тезисами: что прозвучало, а что нет.

Показать ответ и разбор

Коротко

SimpleJpaRepository.save сначала решает, новая ли сущность: по умолчанию по id, равному null, а если есть @Version или реализован Persistable, по ним. Для новой вызывается persist, для старой merge, который при необходимости загружает запись и возвращает управляемую копию, поэтому дальше работаю с результатом save.

Что должно прозвучать в ответе

  • isNew: id null, @Version или Persistable

  • Новая: persist, существующая: merge

  • merge возвращает другой управляемый объект

  • Вручную заданный id: лишний SELECT

  • Внутри транзакции изменения сохраняются через dirty checking без save

  • SQL уходит при flush, а не в момент save

Что могут спросить следом

  • Когда нужен saveAndFlush?
  • Как Hibernate узнаёт, что сущность изменилась?

Разбор

SimpleJpaRepository.save сначала решает, новая ли сущность: по умолчанию по id, равному null, а если есть @Version или реализован Persistable, по ним. Для новой вызывается persist, для старой merge, который при необходимости загружает запись и возвращает управляемую копию, поэтому дальше работаю с результатом save. Сюрприз с вручную заданным UUID: сущность считается не новой, и каждая вставка начинается с лишнего SELECT. Второе: для сущности, загруженной в той же транзакции, save не нужен, Hibernate сам найдёт изменения при flush через dirty checking. Третье: save не обязательно сразу пишет SQL, запросы уходят при flush, обычно при коммите или перед запросом. Если нужно получить ошибку constraint прямо сейчас, использую saveAndFlush.

Ответьте сами, а не прочитайте

В тренажёре вопрос попадёт в повторения и вернётся, когда начнёт забываться. Плюс билеты с зачётом: 20 вопросов, не больше 2 ошибок.