@Transactional не се прилага за всички действия на администратора

Забелязваме след актуализацията от Grails 3.1.11 до 3.2.0, че едно действие на контролер вече не работи:

@Transactional(readOnly = true)
class RoomPlanController {
    ...
    def show(RoomPlan roomPlan) {
        ...
    }
    def getRooms(RoomPlan roomPlan) {
        ...
    }
}

Проблемът е, че когато извикаме roomPlan/getRooms/1 roomPlan е null. Ако извикаме действието show със същия параметър roomPlan е зададен правилно.

Извикването на getErrors() вътре в контролера ни дава следното съобщение за грешка:

Не може да се получи текущата сесия на хибернация; вложеното изключение е org.hibernate.HibernateException: Не е намерена сесия за текущата нишка

който има своя произход от grails.artefact.Controller.initializeCommandObject. След още известно отстраняване на грешки забелязах разлика в проследяването на стека между show и getRooms

Stacktrace на show:

show:100, RoomPlanController (at.byte_code.businessSuite.hotel)
$tt__show:-1, RoomPlanController (at.byte_code.businessSuite.hotel)
doCall:-1, RoomPlanController$_show_closure13 (at.byte_code.businessSuite.hotel)
invoke0:-1, NativeMethodAccessorImpl (sun.reflect)

Stacktrace на getRooms:

getRooms:109, RoomPlanController (at.byte_code.businessSuite.hotel)
getRooms:-1, RoomPlanController (at.byte_code.businessSuite.hotel)
invoke0:-1, NativeMethodAccessorImpl (sun.reflect)

Съобщението за грешка и различното проследяване на стека ни позволяват да приемем, че има нещо общо със сесията/транзакцията на базата данни и след добавяне на @Transactional(readOnly = true) към действието всичко работи според очакванията и преди актуализацията до grails 3.2.0. Ако премахнем анотацията и отново се провали.

Не успяхме да видим проблема в нито един друг контролер и не успяхме да го възпроизведем в малък тестов проект. Вече се опитахме да възстановим проекта, също и на напълно нова работна станция, която не бяхме.

Някой друг наблюдавал ли е подобен проблем?


person Andreas    schedule 08.10.2016    source източник
comment
Може би пропускам нещо тук (много хора извършват сервизна работа в контролер). не трябва ли транзакциите да се използват в контекста на услугите? Да не казвате това, което сте повдигнали, не е валиден въпрос. Просто около най-добрия подход и правилното използване   -  person V H    schedule 08.10.2016
comment
Вие сте прав, но контролерите, генерирани от Grails, включват анотации. Предполагам, че това е така, защото в момента няма скрипт, който автоматично да генерира съответна услуга, а само празна, така че логиката трябва да е била, че е по-добре да има правилно разграничаване на транзакцията (действията за запазване/актуализиране/изтриване имат @Transactional и останалите имат @Transactional(readonly=true)) на грешното място, отколкото изобщо.   -  person Burt Beckwith    schedule 08.10.2016
comment
действието изобразява само някои данни от модела, така че IMHO отделна услуга е ненужна и режийна. Може би греша, но това е начинът, който се предлага от генерираните контролери на grails, както посочи Бърт Бекуит.   -  person Andreas    schedule 09.10.2016
comment
Не бих казал, че изобщо се предлага. Това е просто така. Предложеният и правилен начин всъщност е да използвате услуга. Разходите за наличие и използване на услуга са толкова малки в сравнение с цялостното приложение, че е смешно.   -  person Joshua Moore    schedule 09.10.2016


Отговори (1)


Не мисля, че дори ще имате нужда от @Transactional(readOnly = true) в контролера.

Grails контролерите са по подразбиране само за четене. Можете просто да изтриете анотацията от контролера.

Обратно, класът на обслужване на Grails е транзакционен по подразбиране. Ако трябва да извикате метода save(), по-желателно е да извикате този метод в класа на услугата.

person elixir    schedule 10.10.2016
comment
Без @Transactional обвързването на данни на класове на домейн не работи, тъй като контролерите по подразбиране не са транзакционни. Въпросът е дали някой друг е забелязал проблема, че транзакционната анотация на ниво клас не се прилага към всички действия - person Andreas; 10.10.2016
comment
Не мисля, че @Transactional има нещо общо със свързването на данни със свойствата на класовете на домейна. Когато съм приложил транзакционна анотация на ниво клас, тя се прилага за всички действия. Проверете правилата си за UrlMapping, за да се уверите, че правилото, приложимо за show(), е приложимо и за getRooms() - person elixir; 10.10.2016
comment
Е, ТОВА е действителният проблем, че анотацията на ниво клас не се прилага. работи в grails 3.1.x, не успява в 3.2. Поне за този контролер. Не можем да наблюдаваме или възпроизведем грешката в други контролери. Тъй като не можем да възпроизведем проблема в тестов проект, не можем да създадем билет за проблем в проекта на grails и питаме тук, ако някой наблюдава същия проблем, за да открие основната му причина. - person Andreas; 11.10.2016