Сократить время обработки для выхода из метода Service обратно в метод Controller - PullRequest
0 голосов
/ 01 июня 2018

В моем приложении Grails я создаю множество отдельных DomainObject во время одного вызова ссылки сохранения:

import grails.converters.JSON

class SaveController {
    def saveService

    def save() {
        println (new Date()) + " Enter SaveController.save()."

        Map status = saveService.save(params)
        println (new Date()) + " Finished calling saveService.save()."

        render status as JSON
    }
}

Ссылка вызывает службу для сохранения каждого ее содержимого в базе данных.:

import org.codehaus.groovy.grails.web.servlet.mvc.GrailsParameterMap

class SaveService {
    Map save(GrailsParameterMap params) {
        List<DomainObject> dos = new ArrayList()

        println (new Date()) + " Iterate list and create DomainObject per element."
        params.list.each { l ->
            dos.push(new DomainObject(l))
        }

        println (new Date()) + " Started saving all DomainObjects."
        dos.each { d ->
            d.save()
        }

        println (new Date()) + " Finished saving all ${dos.size()} DomainObjects."

        return [done: true]
    }
}

Проблема в том, что он задыхается в определенной части процесса, что очевидно для отпечатков, которые я разместил:

Fri Jun 01 21:47:55 SGT 2018 Enter SaveController.save().
Fri Jun 01 21:47:55 SGT 2018 Iterate list and create DomainObject per element.
Fri Jun 01 21:47:55 SGT 2018 Started saving all DomainObject.
Fri Jun 01 21:48:13 SGT 2018 Finished saving all 4316 DomainObject.
// Waits from some minutes before reaching the next println.
Fri Jun 01 21:52:02 SGT 2018 Finished calling saveService.save().

Я предполагаю, что это требует времени для сохранения /совершая каждый отдельный .save() вызов в базу данных.У меня вопрос, есть ли способ, которым я могу изменить код, чтобы он фиксировал все элементы List<DomainObject> dos один раз в целом, тем самым исключая длительное время, необходимое для выхода из saveService.save().

Я пытался изменить d.save() на d.save(flush: true), но скорость осталась прежней.Я ищу, может быть, отличный Closure, который будет автоматически фиксировать транзакции внутри него, когда это будет сделано, что-то вроде этого (я не знаю, есть ли фактический Closure как это):

commitOnceDone { session -> 
    dos.each { d ->
        d.save()
    }
}
// Once reached here, will fire a single COMMIT; that will affect
// all transactions that happened inside the Closure

Ответы [ 2 ]

0 голосов
/ 01 июня 2018

Вам нужно пакетировать вкладыши.Для этого вам нужно две вещи:

Для действительно простого использования / тестирования вы можете использовать это в application.groovy:

grails.gorm.default.mapping = {
    'id'(generator: 'increment') // The application instance will generate the ID, so it cannot be clustered 
}

Пт Июн 01 21:48:13 SGT 2018 Закончено сохранение всех 4316 DomainObject.

Обратите внимание, что во время печати этого в БД ничего не сохраняется, так как вы не сбросилисеанс гибернации еще нет.Для пакетной обработки не ставьте «flush: true» в вызове .save (), чтобы Hibernate пакетировал вставки, если вы настроите приложение для пакетной обработки.

Возможны и другие варианты оптимизации, но эта должна бытьсамый большой.

0 голосов
/ 01 июня 2018

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

Подробнее см. в разделе о декларативных транзакциях в документах .

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