JPA Entity Manager Merge без изменений в объекте

Я пытаюсь использовать метод слияния Entity Manager для обновления объекта в базе данных, когда в объекте нет изменений. Скажем, строка имеет следующие атрибуты:

id             DECIMAL(11) NOT NULL,
name           CHAR(20) NOT NULL, 
lastModified   TIMESTAMP NOT NULL FOR EACH ROW ON UPDATE AS ROW CHANGE TIMESTAMP

И скажем, у меня есть объект (назовем его Person) в базе данных со следующими атрибутами:

{id: 1, name: "example", lastModified: 2019-05-22 16:24:54.771}

Таким образом, атрибут lastModified обновляется базой данных каждый раз при изменении строки.

Теперь, когда я сначала извлекаю объект, а затем обновляю имя человека на «пример» (то же значение, которое у него уже есть в базе данных), а затем использую слияние для его обновления, атрибут lastModified, похоже, не обновляется в дб. то есть

Person person = em.find(Person.class, 1)
person.setName("example")
em.merge(person)

После вышеперечисленных действий последний Modified по-прежнему 2019-05-22 16:24:54.771 (то же самое, что и ранее). Теперь, если бы я изменил имя, т.е.

Person person = em.find(Person.class, 1)
person.setName("new name")
em.merge(person)

Так что теперь lastModified также обновился бы.

Любая помощь с этим? Может кто-нибудь объяснить мне, почему строка не обновляется, когда в объект не вносятся изменения? :) Спасибо!

когда мы вызываем слияние JPA (сущность), если какие-либо изменения, внесенные в сущность, будут сохраняться в базе данных, а также наоборот. поскольку в объекте Person нет изменений (когда вы обновляете одно и то же имя в объекте person). Таким образом, он не будет обновлять запись в базе данных.

AssenKhan 22.05.2019 15:44

как бы то ни было, если вы хотите добиться этого, вы можете изменить дату последнего изменения, например, this person.setLastmodified Date(new Date()).

AssenKhan 22.05.2019 15:48
3 метода стилизации элементов HTML
3 метода стилизации элементов HTML
Когда дело доходит до применения какого-либо стиля к нашему HTML, существует три подхода: встроенный, внутренний и внешний. Предпочтительным обычно...
Формы c голосовым вводом в React с помощью Speechly
Формы c голосовым вводом в React с помощью Speechly
Пытались ли вы когда-нибудь заполнить веб-форму в области электронной коммерции, которая требует много кликов и выбора? Вас попросят заполнить дату,...
Стилизация и валидация html-формы без использования JavaScript (только HTML/CSS)
Стилизация и валидация html-формы без использования JavaScript (только HTML/CSS)
Будучи разработчиком веб-приложений, легко впасть в заблуждение, считая, что приложение без JavaScript не имеет права на жизнь. Нам становится удобно...
Flatpickr: простой модуль календаря для вашего приложения на React
Flatpickr: простой модуль календаря для вашего приложения на React
Если вы ищете пакет для быстрой интеграции календаря с выбором даты в ваше приложения, то библиотека Flatpickr отлично справится с этой задачей....
В чем разница между Promise и Observable?
В чем разница между Promise и Observable?
Разберитесь в этом вопросе, и вы значительно повысите уровень своей компетенции.
Что такое cURL в PHP? Встроенные функции и пример GET запроса
Что такое cURL в PHP? Встроенные функции и пример GET запроса
Клиент для URL-адресов, cURL, позволяет взаимодействовать с множеством различных серверов по множеству различных протоколов с синтаксисом URL.
2
2
2 833
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Ответ принят как подходящий

Когда вы используете merge, Hibernate сначала запускает оператор Select в кортеже, который вы пытаетесь объединить. Этот выбор выполняется, чтобы получить последнее состояние кортежа, а затем запустить обновление в базе данных с данными, которые изменились в вашем кортеже.

Как вы говорите в своем примере, вы не изменили никаких данных, поскольку пытаетесь обновить имя до того же, что и раньше, поэтому спящий режим не будет запускать никаких обновлений базы данных.

Вы можете прочитать больше об этом, ссылаясь на Hibernate Dirty Checking Mechanism.

Если вы действительно хотите обновить этот столбец, даже если данные не изменились, вы должны сделать это на уровне приложения, установив его вручную при сохранении объекта Person:

person.setLastModified(LocalDateTime.now())

Спасибо Марсело за разъяснение! :)

Ville Lehtonen 24.05.2019 12:26

Просто дополнение к ответу Марсело:

Вы должны использовать merge() только при «объединении» данных, которые находятся вне постоянного контекста. Например, когда вы получаете объект Person из REST API, не связанный с областью транзакции, и вы хотите подключить его к контексту, а затем сохранить его внутри EJB.

В своем коде удалите оператор em.merge(person). Hibernate/JPA обнаружит изменения, когда вы используете методы set() через прокси, и сгенерирует SQL-команды скрытно.

В дополнение к ответу Марсело вы можете принудительно обновить сущность с помощью блокировки. Используйте следующее:

em.lock(person, LockModeType.OPTIMISTIC_FORCE_INCREMENT)

Другие вопросы по теме