Ваша проблема связана с передачей совершенно новой сущности User
, поэтому Hibernate не может использовать кэшированную версию, которая уже была извлечена из базы данных, и решать, какие столбцы обновлять динамически.
Итак, попробуйте сделать следующее, чтобы подтвердить правильное поведение @DynamicUpdate
;
В эксплуатации;
@Transactional
public User save(User newUser) {
User currentUser = userRepository.get(newUser.getId());
// handle merging of updated columns onto currentUser manually or via some mapping tool
currentUser.setName(newUser.getName());
return userRepository.save(currentUser);
}
Используя вышеуказанную логику вместе с динамической аннотацией обновления, вы сможете увидеть обновление столбца только с именем, если у вас не включен какой-либо аудит или используется столбец @Version
'ed.
Если обновленные столбцы всегда одинаковы, то лучше использовать updatable = false
для столбцов, которые не являются целью обновления в их определениях @Column
, поскольку использование @DynamicUpdate
очень неэффективно, поскольку генерирует каждый sql заново, никогда не используя кэшированные sqls. Но будьте осторожны, используя эту функцию, поскольку вы вообще не сможете обновить эти столбцы.
Я не рекомендую использовать @Query
, если у вас нет случая, когда собственный JPA / Hibernate недостаточен, но если у вас есть вариант использования для обновления только целевого набора столбцов, это лучший выбор, и наиболее эффективный.
Если обновленных столбцов много и они могут сильно различаться, либо определите логику сопоставления вручную между newUser
и currentUser
, либо используйте некоторые инструменты сопоставления, такие как Orika
, у меня есть аналогичная автоматизированная структура, в которой сотни сущностей пропатчены через эти средства отображения, что позволяет чрезвычайно универсальным образом обрабатывать многие операции CRUD.