Короче говоря, я пытаюсь решить, как восстановить некоторые ошибки базы данных в приложении Grails с помощью Hibernate и продолжить транзакцию, пропуская неудачные обновления строк, которые часть партии изменений.Как исправить ошибки базы данных в Grails внутри транзакции
Приложение использует Grails 2.3.11, но я также пробовал с версией 1.3.8 с аналогичными неудачными результатами.
В основном существует класс обслуживания Grails, который выполняет итерацию по списку импортированных записей и пытается соответствующим образом обновлять связанные основные записи. В определенных ситуациях могут возникать исключения во время звонка domain.save(flush:true)
. org.hibernate.exception.DataException
выброшено из-за таких проблем, как (Усечение данных: слишком длинные данные для столбца ...).
На данный момент я попытался:
- Отключение транзакций
- Использование domainObj.withTransaction() для каждой отдельной записи
- Trying различные @Transactional аннотаций
- Calling domain.clearErrors() и domain.discard() после исключения исключения
- Пробовал с помощью вложенной службы с транзакционной аннотацией с noRollbackFor, как показано ниже
- Рядом других подходов, но ничего я пробовал работал
Пример код:
@Transactional
class UpdateService {
public updateBatch(Integer batchId) {
...
list.each { record ->
record.value = 123
try {
nestedService.saveDomain()
} catch (e) {
record.clearErrors()
record.discard()
}
}
batch.status = "POSTED"
batch.save()
}
}
@Transactional
class NestedService {
@Transactional(propagation = Propagation.REQUIRED, noRollbackFor = RuntimeException.class)
public void saveDomain(domainObj) throws RuntimeException {
if (domainObj.validate() && domainObj.save(flush:true) {
log.info "domain $domain was saved"
}
}
}
После произошла ошибка, я не могу очистить сеанс спящего режима. При каждой последующей обновляемой записи я получаю сообщение об ошибке:
org.hibernate.StaleObjectStateException: Row was updated or deleted by another transaction
, где он указывает исходный номер отказавшего домена.
Редакция:
Вахид, спасибо за предложения. Я пробовал это. Я понял, что одна проблема заключается в том, что я передаю объекты через границы транзакций. Так что я экспериментировал с классом NestedService сделать что-то вдоль линий:
@Transactional(propagation = Propagation.REQUIRE_NEW)
public void saveDomain(domainObj) {
def newObj = new Domain.get(domainObj.id)
newObj.properties = domainObj.properties
if (newObj.validate() && newObj.save(force:true)) { ... }
я ожидал, что работать, но оригинальный domainObj все еще терпит неудачу, хотя я не называю сохранения на нем. Очень странно ...
попробовал REQUIRES_NEW для вашего распространения? Я добавил несколько заметок о кислоте здесь https://github.com/vahidhedayati/documentation/blob/master/grails/acid.md, недавно прочитав это http://blog.perezalcolea.info/2014/06/09/Grails- Транзакции-Revisited.html и этот http: // sacharya.com/transaction-in-grails/ – Vahid
Vahid - посмотрите мои комментарии в исходных комментариях, где я добавил ревизию. –
Что делать, если вы попытались newObj.merge() перед проверкой и сохранением, также вам удалось прочитать последнюю часть 3-й ссылки о пакетной обработке в спящем режиме. Однако никогда не рекомендовал бы его для Контроллеров. Если у вас есть время https://www.youtube.com/watch?v=JNey9T--rLE watch, Берт объясняет транзакции действительно хорошо. Нужно смотреть его несколько раз больше. – Vahid