Вызов grails ajax строка-была обновлена-или-удалена другой-транзакцией-или-несохраненным-отображением-значением-была
Я использую Grails 2.3.5, и у меня есть контроллер, который содержит ajaxDelete
метод. Этот метод получает имя в виде строки объекта, который я хочу удалить. Я использую сервис для удаления объекта, который я вызываю из моего контроллера.
При первом вызове метода deleteSvnUser из служб пользователь SVN удаляется, и мой div на странице обновляется с предупреждением о том, что пользователь был удален. Во второй раз, когда я удаляю пользователя, я получаю следующую ошибку:
row-was-updated-or-deleted-by-another-transaction-or-unsaved-value-mapping-was...
Я попытался пару вещей, чтобы обойти это:
- Добавление аннотации @transactional к моему сервису (что мне и не нужно, потому что по умолчанию она должна быть транзакционной).
- очистка моих удалений (flush:true)
- Обновление объекта перед его удалением (.refresh)
- Блокировка объекта, когда я его получаю (entity.lock(id))
Ничто из вышеперечисленного не сработало. Я не уверен, что еще нужно сделать, чтобы обойти это. Кто-нибудь может помочь? мой код ниже:
контроллер
class SvnUserController {
def svnUserService
def ajaxDelete() {
if (!params.selectedSvnUser) {
request.error = "The selected Svn User does not exist"
render(template:"svnUserList", model:[svnUserInstanceList: SvnUser.list(params).sort{it.name}, svnUserInstanceTotal: SvnUser.count()])
return
}
String outcome = svnUserService.deleteSvnUser(params.selectedSvnUser)
switch (outcome){
case "":
request.message = "Svn User ${params.selectedSvnUser} deleted"
break
default: request.error = outcome
}
}
def svnUsers = svnUserService.getAllSvnUsers(params)
render(template:"svnUserList", model:[svnUserInstanceList: svnUsers, svnUserInstanceTotal: svnUsers.size()])
return
}
}
обслуживание
class SvnUserService {
public String deleteSvnUser(String userName) {
String outcome = ""
try {
SvnUser svnUserInstance = SvnUser.findByName(userName)
def groups = SvnGroupController.findAllBySvnUserName(userName)
groups.each { SvnGroup group ->
group.removeFromSvnUsers(svnUserInstance)
group.save()
}
def userPermissionsList = UserPermission.findAllBySvnUser(svnUserInstance)
userPermissionsList.each {
def repoDirectory = it.repositoryDirectory
repoDirectory.removeFromUserPermissions(it)
it.delete()
}
svnUserInstance.merge()
svnUserInstance.delete()
}
catch (DataIntegrityViolationException e) {
outcome = "A error occurred while attempting to delete the Svn User from file."
}
return outcome
}
}
Трассировка стека выглядит следующим образом:
Error |
2014-06-10 15:10:07,394 [http-bio-8080-exec-6] ERROR errors.GrailsExceptionResolver - StaleObjectStateException occurred when processing request: [POST] /subzero/svnUser/ajaxDelete - parameters:
selectedSvnUser: ruby2
Row was updated or deleted by another transaction (or unsaved-value mapping was incorrect): [com.uk.nmi.subzero.SvnGroup#2]. Stacktrace follows:
Message: Row was updated or deleted by another transaction (or unsaved-value mapping was incorrect): [com.uk.nmi.subzero.SvnGroup#2]
Line | Method
->> 72 | deleteSvnUser in com.uk.nmi.subzero.SvnUserService
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
| 87 | ajaxDelete in com.uk.nmi.subzero.SvnUserController
| 200 | doFilter . . in grails.plugin.cache.web.filter.PageFragmentCachingFilter
| 63 | doFilter in grails.plugin.cache.web.filter.AbstractFilter
| 1145 | runWorker . . in java.util.concurrent.ThreadPoolExecutor
| 615 | run in java.util.concurrent.ThreadPoolExecutor$Worker
^ 744 | run . . . . . in java.lang.Thread
1 ответ
Я не вижу никаких проблем с вашим кодом. Граальс должен нормально обрабатывать транзакции.
Если ваше сопоставление объектов настроено правильно, svnUserInstance.delete()
вызов должен также удалить дочерние объекты, так что я не думаю, что вам даже нужны строки между svnUserInstance = SvnUser.findByName(userName)
и удаление.
Как вы звоните ajaxDelete? Есть ли вероятность, что его неправильно называют во второй раз?