Grails: как структурировать транзакции, когда я хочу продолжить проверку даже после того, как транзакция уже провалилась - PullRequest
0 голосов
/ 09 февраля 2012

Мои пользователи загружают csv или xls или что-то еще, и каждая строка будет экземпляром объекта домена, который я сохраняю. Если какая-либо из строк потерпит неудачу, я хочу, чтобы все было отменено, но я также хочу возвращать ошибки для любых строк, которые потерпят неудачу позже. Давайте сделаем пример:

Класс домена:

MyDomainClass{
  String fieldOne
  BigDecimal fieldTwo
}

Введите:

ThisLineWorks,4.4
ThisLineFails,BecauseOfThis
How would I also get an error, for this line as well considering the last one would have rolled back the transaction already?

Фэнтези Выход:

OK|ThisLineWorks,4.4
field 2 isn't a number|ThisLineFails,BecauseOfThis
field 2 isn't a number|How would I also get an error, for this line as well considering the last one would have rolled back the transaction already?

Ответы [ 2 ]

2 голосов
/ 09 февраля 2012

Вы можете проверить объекты без необходимости их сохранения: (http://grails.org/doc/2.0.x/guide/validation.html#validatingConstraints). Таким образом, в службе вы можете создать все объекты, затем проверить все объекты, а затем сохранить все объекты. Что-то похожее на :

def serviceMethod(data) {
    def listOfObjects = createObjectsFromData(data)
    listOfObjects*.validate()
    def anErrorOccurred = listOfObjects.find {it.hasErrors()} != null
    if(anErrorOccurred) {
        return listOfObjects
    }
    listOfObjects*.save(validate: false) //you could use the validate:false or leave it out.  I figure since we've already validated that you could do without re-validating.
}

Таким образом, вы можете собрать все свои ошибки, и вам не придется беспокоиться об откате транзакции. Проблема с этой настройкой заключается в том, что вы будете создавать N чисел объектов и удерживать их все. Если ваш файл длиннее 100 тыс. Строк (немного обоснованное предположение о том, где вы начнете страдать), это может вызвать некоторые проблемы с производительностью. Если вам не нравится описанный выше метод, вы можете обработать транзакцию вручную: (http://grails.org/doc/2.0.x/ref/Domain%20Classes/withTransaction.html)

def serviceMethod(data) {
    MyDomainClass.withTransaction { status ->
        def listOfObjects = []
        data.each {
            def domainObject = createObjectFromData(it)
            lisOfObjects << domainObject.save()
        }
        def anErrorOccurred = lisOfObjects.find {it.hasErrors()} != null
        if(anErrorOccurred) {
           status.setRollbackOnly()  //will roll back all of the transactions surrounded by the .withTransaction {}
        }
    }
}

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

2 голосов
/ 09 февраля 2012

вот что я думаю:

1.Установите флаг, который сигнализирует о ВСЕХ ОЧИСТКАХ, и завершите транзакцию вручную в конце, если все ясно.Зафиксируйте каждую строку в отдельной транзакции, фиксируя ошибки неудачных строк и пропуская ошибки.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...