Grails 3.3: сохраняется только первое сохранение ()? - PullRequest
0 голосов
/ 04 июля 2018

Сохраняется ли только первое save () в экземпляре объекта домена?

Среда: Grails 3.3.5, GORM 6.1.9 Я считаю, PostgreSQL 9.5, JDK 1.8.0_171, Ubuntu 16.04.

Мое приложение создает экземпляры Recital (объект домена) на основе входных данных из ряда текстовых файлов. Это загрузка базы данных, поэтому все происходит за один вызов контроллера, вызывая метод службы. Одна транзакция.

Сервисный метод анализирует входные потоки в поисках сечений. Когда он находит его, он пытается findBy метод (сноски нумеруются). Если есть сольный концерт с указанным номером, он обновляет его из входных данных и сохраняет (). В противном случае он создает новый экземпляр из входных данных и сохраняет (). failOnError везде для хорошей меры. Сольные концерты не принадлежат ничего, никаких каскадных проблем.

Логика программы не может определить, является ли модификация последним обновлением экземпляра. Таким образом, есть save () после каждого изменения. Но это не работает. Кажется, вы можете сохранить () только один раз.

Чистый результат, найденный в базе данных, заключается в том, что сохраняется только первое сохранение (). При отладке работающей программы я могу убедиться, что экземпляры полностью обновлены в памяти.

Если это правильно, в документации должно быть сказано: Метод save сообщает контексту постоянства, что экземпляр должен быть сохранен или обновлен в его текущем состоянии. Любые и все модификации после этой точки (в той же транзакции) будут игнорироваться. Объект не будет сохранен сразу, если не используется аргумент flush ...

P.S. Документация save () объясняет "flush: true", так как сбрасывает контекст персистентности . Это имеет мало объяснительной ценности для новичка. Вот некоторые синонимы «очистка»: очистка, удаление, удаление, очистка, очистка, удаление. Пользователь базы данных может получить его как ROLLBACK, а не как COMMIT. Объяснение, конечно, терминология гибернации. Хорошо, если документация Grails в основном автономна. (Боковой вопрос в той же части документации.)

Ответы [ 2 ]

0 голосов
/ 06 июля 2018

Прежде чем слишком много людей будут тратить на это свое время, вот новое понимание.

Так получилось, что домен Recital имеет встроенный компонент. Обновления в моем приложении затрагивают только элементы встроенного компонента.

Я проверил, что для трех конкретных обновлений одного и того же экземпляра члены корректно обновляются в памяти. Однако после каждого из трех обновлений recital.isDirty () возвращает false, аналогично recital.isDirty ('body'), где body - это встроенный компонент.

Мой вывод заключается в том, что обновление встроенного компонента не обязательно устанавливает флаг для грязного экземпляра. Так что не сохраняется. Забудьте теорию, предложенную в оригинальном вопросе. Кажется, есть ошибка Grails / GORM.

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

РЕДАКТИРОВАТЬ: Не ошибка. GORM теперь требует, чтобы внедренные классы были помечены @DirtyCheck, чтобы произошла грязная проверка. Дело закрыто.

0 голосов
/ 05 июля 2018

Я могу видеть описанное поведение, только если не участвую в транзакции, что в любом случае является плохой практикой. Поэтому я подозреваю, что вы не участвуете в транзакции или не участвуете в ней постоянно. Вы уверены, что все задействованные методы помечены @Transactional?

Значение flush: true состоит не в том, чтобы поместить коммит, а в выполнение вставки / обновления базы данных, поэтому предложение Туомаса должно сработать, но если я прав, вы все еще вне транзакции, и если Исключение происходит, у вас есть частично сохраненные данные. Только если вы оставите все методы, аннотированные @Transactional, коммит будет помещен, но если будет необработанное исключение RunTimeException, вы получите откат.

Рассмотрим это в рамках одной транзакции:

Recital.save(); Racital.count() -> 0

Recital.save(flush: true); Racital.count() -> 1

Если вы загляните в журналы SQL, вы увидите, что только первый .save () нового объекта сохраняется, все обновления задерживаются до тех пор, пока вы не покинете транзакцию, что может сэкономить накладные расходы. Я полагаю, поскольку вы не участвуете в транзакции, последнее обновление никогда не будет выполнено.

Кстати, IMO документация Grails - один из лучших проектов OSS, которые я знаю. Вы можете увидеть подсказки о подводных камнях, если просмотрите их позже, но они не повторяют их повсюду.

...