Заключение
Это зависит от того, содержится ли метод в транзакции или нет.
- В транзакции: приведенный выше код работает неявно.
- Не в транзакции:
.save()
должен быть явно вызван для обновления базы данных.
Как я могу обнаружить подобные случаи и точно знать, когда использовать метод .save()
и когда я могу его игнорировать?
- Метод
.save()
должен вызываться для модифицированной сущности явно, если:
- Изменяющийся код не относится к транзакции .
- Недавно созданная сущность:
new Car()
.
- Объект сущности получается извне, а не из базы данных в рамках той же транзакции. (Например, уже сохранено в
List
до начала транзакции.)
- Метод
.save()
не должен вызываться для сущностей, которые запрашиваются из JPA в рамках той же транзакции. (Например, carRepository.findById(id)
и другие подобные методы).
Сделка
Если приведенная выше последовательность событий вызывается из метода, аннотированного @Transactional
, то он будет работать как положено.
Затем созданный объект Car
становится управляемым контекстом постоянства, и все изменения в нем, в пределах одной и той же транзакции, сбрасываются после завершения транзакции.
Нет транзакций
Если описанный выше метод не принадлежит какой-либо транзакции, все изменения объектов являются локальными (свойства объекта изменяются, но не сбрасываются в базу данных).
Вот почему вызов persist()
или merge()
(в вышеприведенном случае save()
, который использует эти два для внутреннего использования) должен выполняться явно для сброса изменений.
Лучше использовать транзакции
При сохранении одного объекта выполняется один SQL-запрос, который является атомарным, то есть сама транзакция. Если последовательность событий базы данных не содержится в транзакции, то каждый вызов save()
действует как отдельная «транзакция».
Обычно это плохая практика, потому что, если одна из более поздних «транзакций» завершается неудачно (что-то вроде Exception
сгенерировано), предыдущие успешные транзакции уже сброшены, возможно, приведя базу данных в недопустимое состояние из бизнеса. логическая перспектива.
Открыть сеанс в представлении
Поведение не имеет ничего общего с OSIV.
OSIV сохраняет базу данных сеанс открытой во время рендеринга представления, так что дальнейшие запросы (транзакции) могут быть выполнены после завершения основной обработки запроса на уровне представления. Использование OSIV широко считается анти-паттерном.