Сущность отделяется, когда ей нужно управлять
Рассмотрим контроллер-сервис-хранилище арки.
Успешный метод в TokenService объявил, что я прав по существу.
@Transactional
public Token getByString(String tokenString) {
Token t = tr.loadTokenByString(tokenString);
t.setTokenType("SERVICE MODIF"); // note this test line works and changes are propagated to db
em.flush();
return t;
}
Теперь мы внутри отображения обработчика контроллера, вызывающего предыдущий метод службы и извлекающего токен:
logger.info(urlToken);
Object obj;
Token token;
obj = tokenService.getByString(urlToken);
User u;
if (obj != null) {
token = (Token) obj;
// tokenService.save(token); - am angry lost detached entity throwing exception that i am detached
token.setTokenType("helllo"); // this does not propagate to db since entity is detached
logger.info(token.toString());
u = token.getUser();
userService.activateUser(u);
}
Как видно из комментариев, следующий setTokenType
внутренний вызов контроллера ничего не делает, поэтому я позвонил save
проверить состояние, которое без дальнейших угадываний уведомило меня о том, что объект стал отделенным.
Означает ли это, что я должен сделать все изменения внутри классов обслуживания? Что не так с контекстом контроллера, если мне просто нужно вызвать один мутатор, я не хочу, чтобы меня заставляли создавать целую цепочку репозитория-службы, чтобы сделать это из контроллера Oo
Где-то глубоко в моем мозгу я вспоминаю, что существует потребность в каком-то магическом фильтре для учета контекста контроллера, но это было давно, и я не могу вспомнить, какой тип фильтра требуется. Может быть, я совершенно не прав.
Я сомневаюсь, что смог бы merge
внутри контроллера, так как даже асфаик .flush
выдает исключение всякий раз, когда я забываю объявить сервис транзакционным. И я сомневаюсь, что можно или даже правильно объявить транзакционный метод обработчика контроллера и контекст персистентности autowire непосредственно для вызова слияния.
Конечно, идеальным сценарием будет поддержание постоянного состояния объекта, даже когда он получен цепным вызовом контроллера.
1 ответ
Когда вы объявляете этот метод транзакционным, он будет транзакционным. Это и только это.
После завершения транзакции вы не можете вносить в нее какие-либо изменения в том смысле, что независимо от того, с каким ссылочным объектом вы связались, он больше не управляется сеансом. (Потому что транзакция окончена).
Если вы хотите изменить объект в управляемом состоянии, сделайте это в транзакционном методе самостоятельно (в рамках той же транзакции).