Grails требует явного сброса для сохранения изменений

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

User.groovy

package helloworld

class User {
    String name
    String password
    Date   register_date

    static hasMany = [tasks: Task]
    static mapping = {
        tasks cascade: "all-delete-orphan"
    } 
    static constraints = {
    }
}   

Task.groovy

package helloworld

class Task {
    String description
    Date due
    Boolean deleteFinished
    Boolean finished

    static belongsTo = [owner: User]
    static constraints = {
    } 
}   

TodoController.groovy (проблема?)

...
def persist() {
    User u = User.get(session["user_id"])
    Boolean df = params["deleteFinished"] != null
    Task t = new Task(description: params["description"], due: params["due"], deleteFinished: df, finished: false)
    u.addToTasks(t)
    u.save(flush: true) //problem point
    redirect(action: 'index')
}

...

Итак, согласно всей документации, которую я читал, сеанс гибернации должен быть сброшен и закрыт в конце каждого запроса, но, похоже, здесь это не так. u.save(flush: true) работает должным образом, сохраняя любые изменения или добавленные дочерние элементы (задача t), но когда я использую u.save(), любые изменения, внесенные в u, а также Task t, не сохраняются после завершения запроса. Что еще более странно, если я перенесу код в сервис Grails с инкапсулированными методами транзакции, u.save() заработает. Я проверил все, что мог придумать. Мои объекты домена прикреплены, они действительны, они обнаруживают, что они грязные, когда они меняются. Может ли кто-нибудь помочь мне разгадать эту загадку?


person Scott Jordan    schedule 27.05.2014    source источник
comment
Этот билет является древним в годы stackoverflow ... но вы помните, какая это была версия грааля? Я занимаюсь обновлением некоторых старых проектов grails и заметил, что поведение при сбросе определенно меняется между версиями grails. Вы можете добавить def sessionFactory в свой контроллер, а затем println sessionFactory.currentSession.flushMode в действие вашего контроллера. Если режим промывки автоматический, он должен промыть. Если FlushMode ручной, вам нужно вручную вызвать flush.   -  person burns    schedule 29.06.2018


Ответы (1)


По умолчанию в контроллерах не включены транзакции. Перемещение кода в службу (по умолчанию они транзакционные) или аннотирование вашего метода как транзакционного должно решить вашу проблему.

import grails.transaction.Transactional

    @Transactional
    def persist() {
        User u = User.get(session["user_id"])
        Boolean df = params["deleteFinished"] != null
        Task t = new Task(description: params["description"], due: params["due"], deleteFinished: df, finished: false)
        u.addToTasks(t)
        u.save()
        redirect(action: 'index')
    }
person ascu    schedule 27.05.2014
comment
Сделки здесь не имеют значения. Код в контроллере также должен сохранять Задачу без транзакции. - person lukelazarovic; 27.05.2014