Spring Data JPA: сохранить список родителей, где дети были перемещены между родителями в одной транзакции - PullRequest
2 голосов
/ 30 сентября 2019

У меня есть список родителей, у каждого из которых один-ко-многим есть список много-к-одному детям. Удаление сирот включено, и отношения ленивы.

Я использую JpaRepository с Hibernate.

Мне нужно перемещать детей между родителями и сохранять все изменения в одной транзакции.

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

Но когда я помещаю цикл в метод, помеченный @Transactional, чтобы вся процедура сохранения содержалась в одной всеобъемлющей транзакции, которая откатывается в случае сбоя одного из вызовов сохранения,дети будут иногда сохраняться неправильно.

Когда я сохраняю одну за другой в отдельных транзакциях, Hibernate просто обновляет дочернюю строку, если она была перемещена из другого родителя. в родительский объект, который в данный момент сохраняется, но удаляет и повторно вставляет дочерний элемент, если он был удален из родительского элемента, который является cСрочно спасается. Я вижу, что в журналах SQL.

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

Я также пыталсяиспользовать saveAll() вместо цикла в методе @Transactional, тот же эффект.

Перемещение детей между родителями и сохранение всех родителей в одной транзакции не поддерживается сценарием?

1 Ответ

3 голосов
/ 30 сентября 2019

Это не совсем то, что вы ищете, но может быть вариант не использовать дочерние объекты, а вместо этого назначать их копии.

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

После этого вы сможете вызвать CrudRepository#saveAll() в списке родительских объектов, которые были изменены таким образом, и получить ожидаемый результат.

Предостережение заключается в том, что идентификаторы перемещенных потомков будут изменены в базе данных, так как они будут удалены, а затем вставлены заново. Решение не является оптимальным с точки зрения производительности, поскольку вы будете выполнять немного больше работы как на уровне БД, так и на уровне Java.

...