Транзакционное поведение классов обслуживания Grails с цепными вызовами - PullRequest
2 голосов
/ 14 февраля 2011

Я анализирую xml-файлы в своем приложении и немного борюсь за то, как спроектировать это.

Я разрешаю загружать «неполные» деревья наших XML-схем, а это означает, что до тех пор, пока дерево правильно сформировано, оно может быть любым дочерним элементом корневого узла. У большинства узлов есть дочерние узлы, которые содержат только некоторый текст (свойства), но я не включил ничего из этого в мой небольшой пример структуры XML.

<root>
    <childFoo>
        <childBar>
        </childBar>
    </childFoo>
</root>

Любой из этих узлов разрешен. Теперь я разработал XmlInputService, который имеет методы для анализа различных узлов. И я просто определяю в контроллере, какой это тип узла, и соответственно передаю его в сервисный метод.

Таким образом, чтобы сохранить мой код СУХИМ и красивым, я повторно использую свои методы на более высоких уровнях. Если я передам документ типа Root в службу, он будет анализировать любые поля в корне, которые принадлежат непосредственно корню, и передавать дочерние узлы (которые представляют дочерние элементы в моей структуре классов домена) в подходящий метод синтаксического анализа в услуга.

Теперь, если пользователь загружает xml, содержащий нарушения ограничений, то есть элемент с неуникальным именем и т. Д., Я, очевидно, хочу откатить это назад.

Допустим, я вызываю parseRoot () и иду вниз, вызывая parseChildFoo ().

Там я вызываю parseChildBar () для каждого дочернего элемента Bar. Если один из дочерних элементов Bar не может выполнить проверку из-за ограничений или чего-то еще, я, очевидно, хочу каскадно откатить транзакцию вплоть до parseFoo ().

Как бы мне этого добиться?

Ответы [ 2 ]

1 голос
/ 15 февраля 2011

Если у вас есть служба grails, у которой есть метод, который занимается анализом, вы должны выбросить исключение, которое расширяет java.lang.RuntimeException из вашего сервиса, чтобы пользователь мог быть проинформирован о том, что ему нужно изменить свой xml.Таким образом, ваш контроллер перехватит это исключение и предоставит пользователю значимое сообщение об ошибке

Откат любых изменений базы данных будет выполняться Grails / Spring автоматически всякий раз, когда исключение runtimeexception вызывается из метода сервиса.

Преимущество подхода, который я описываю над ответом Виктора, состоит в том, что вам не нужно писать какой-либо код, чтобы позволить откат транзакции в случае сбоя.Grails сделает это за вас.ИМО, использовать закрытие withTransaction внутри сервисного метода не имеет смысла.

Более подробная информация здесь

1 голос
/ 14 февраля 2011

Сделайте эти правила проверки допустимыми для объектов домена.

Если save () нарушает ограничения, генерирует исключение и перехватывает его на верхнем уровне анализа, а затем откатывает всю транзакцию.Например:

meServiceMethod() {
    ...
    FooDomainClass.withTransaction { status ->
        try {
            parseRoot(xml)
        } 
        catch (FooBarParentException e) {
            status.setRollbackOnly()
            // whatever error diagnostics
        }
    }
    ...
}

Или вы можете просто позволить исключению вылететь из метода обслуживания в контроллер - методы обслуживания являются транзакционными по умолчанию.

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