Spring Data CrudRepository возвращает только измененные поля при вызове save ()

Я использую Spring Data (версия 1.13.9.RELEASE) и имею CrudRepository под названием myRepository. Я вызываю myRepository.save(myObject), чтобы перезаписать существующий экземпляр myObject в базе данных, и я указываю некоторые поля myObject как null.

Например:

{
    "prop1": "val1",
    "prop2": null,
    "prop3": "val3"
}

Когда я вызываю myRepository.save(myObject) и читаю возвращаемое значение, все поля myObject, которые я установил как null, возвращаются как null (в этом примере prop2).

Однако значение для prop2 в базе данных НЕ является null после вызова save() - оно все еще имеет предыдущее значение до того, как я вызвал save().

На самом деле это то поведение, которое я хочу в данной конкретной ситуации (игнорировать значения null при вызове myRepository.save()), но я бы хотел, чтобы возвращаемое значение save() отражало то, что на самом деле находится в базе данных после операции, а не только возвращало обновленные поля и поля настройки, указанные как null в null или их значения по умолчанию (например, false в случае логического.

Это ожидаемое поведение CrudRepository в поведении save()?

Просто интересно, правильно ли обновляется ваша база данных?

Pranjal Gore 17.10.2018 21:11

Есть шанс, что это не так. Я использую DynamoDB. Возможно, следует установить в полях значение null. Однако, если это не так, я думаю, что CrudRepository должен в основном повторно запрашивать базу данных при вызове save(), чтобы вернуть самые последние значения. Я не уверен, где он видит эти значения как null (поскольку они не null в Dynamo)

user2121620 17.10.2018 21:20

Второй вопрос .. вы используете Hibernate?

Pranjal Gore 17.10.2018 21:40

@PranjalGore Да, я

user2121620 17.10.2018 21:41

Хорошо. Итак, вам нужно сначала получить самый последний объект, это привязывает объект к постоянному состоянию. Во-вторых, обновите объект (пока он все еще находится в постоянном состоянии) и, наконец, вызовите save.

Pranjal Gore 17.10.2018 21:44

Я также не так хорошо знаком с Spring Data или Dynamo, но я согласен, что он не должен возвращать значения из базы данных, если вы явно не запросите его повторно. Я думаю, вам следует либо вызвать myRepository.saveAndFlush (), либо использовать myRepository.merge ()

Josh 17.10.2018 21:47
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
2
6
768
2

Ответы 2

Чтобы понять проблему, вам нужно немного разобраться в жизненном цикле объекта Hibernate.

Жизненный цикл объекта Hibernate состоит из следующих состояний: 1. Переходное состояние 2. Постоянное состояние 3. Обособленное состояние и т. д.

Когда вы создаете новый объект, он находится в переходном состоянии, а Hibernate не имеет средств обнаружения объектов, присутствующих / созданных в переходном состоянии.

Когда вы вызываете save()saveOrUpdate(), объект переходит из переходного состояния в постоянное, и теперь Hibernate начнет отслеживать все изменения, внесенные в объект (но объект еще не записан в базу данных).

Итак, в вашем случае, поскольку объект не находится в постоянном состоянии, спящий режим не может его распознать и запустит (скорее всего) запрос insert. Однако, если бы объект уже находился в постоянном состоянии, спящий режим знал бы, что некоторые поля изменились, и, следовательно, запустит запрос update.

Вот почему вам нужно убедиться, что объект находится в постоянном состоянии, если вы хотите, чтобы спящий режим запускал запрос update.

Это означает, что транзакция еще не завершена и все изменения находятся только в кеше. Для принудительного обновления вы можете вызвать entityManager.flush() или переместить всю необходимую логику в отдельный общедоступный метод другой службы или менеджера и аннотировать его как @Transactional.

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