Вы не можете сделать Login.withTransaction{ user ->
, так как параметр замыкания, который вы передаете методу withTransaction
, принимает аргумент, который является TransactionStatus
- вы не можете указать тип, только имя.
Но я не уверен, почему вы видите то, что видите, в отношении объема закрытия.Крутая вещь о замыканиях заключается в том, что они заключают в свои рамки, отсюда и название.Таким образом, переменные вне замыкания всегда доступны внутри замыкания.
Вы бы хотели, чтобы User
был загружен внутри блока withTransaction
, хотя он находится в том же сеансе Hibernate, что и транзакция, в противном случае Login
сохранить не удастся, так как User
будет отключен.И используйте load()
, а не read()
, так как вы просто устанавливаете внешний ключ в Login
, поэтому load()
работает лучше всего, поскольку он просто создает прокси и не попадает в базу данных, но делает идентификатор доступнымдля Login
сохранения.По той же причине, по которой вы хотели бы избежать использования метода currentUser
, поскольку это всего лишь ярлык для User.get()
.
Сказав все это, у меня получилось:
grails.plugins.springsecurity.onInteractiveAuthenticationSuccessEvent = { e, appCtx ->
Login.withTransaction { status ->
new Login(user: appCtx.springSecurityService.currentUser).save()
}
}
но поскольку переменная e
является InteractiveAuthenticationSuccessEvent
, вам лучше использовать это:
grails.plugins.springsecurity.onInteractiveAuthenticationSuccessEvent = { e, appCtx ->
Login.withTransaction { status ->
def user = User.load(e.authentication.principal.id)
new Login(user: user).save()
}
}