Почему переключение из AspectJ в режим Proxy приводит к тому, что "TransactionRequiredException: выполнение запроса на обновление / удаление" больше не происходит?
У меня проблема с использованием Spring Data Jpa & Hibernate.
Вот исключение, которое я получаю:
2017-05-21 21:42:20.761 DEBUG 11765 --- [nio-8080-exec-5] o.h.e.t.internal.TransactionImpl : committing
2017-05-21 21:42:20.765 INFO 11765 --- [nio-8080-exec-5] i.StatisticalLoggingSessionEventListener : Session Metrics {
14574 nanoseconds spent acquiring 1 JDBC connections;
0 nanoseconds spent releasing 0 JDBC connections;
55978 nanoseconds spent preparing 2 JDBC statements;
2315850 nanoseconds spent executing 2 JDBC statements;
0 nanoseconds spent executing 0 JDBC batches;
0 nanoseconds spent performing 0 L2C puts;
0 nanoseconds spent performing 0 L2C hits;
0 nanoseconds spent performing 0 L2C misses;
0 nanoseconds spent executing 0 flushes (flushing a total of 0 entities and 0 collections);
0 nanoseconds spent executing 0 partial-flushes (flushing a total of 0 entities and 0 collections)
}
2017-05-21 21:42:20.779 ERROR 11765 --- [nio-8080-exec-5] o.a.c.c.C.[.[.[/].[dispatcherServlet] : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is org.springframework.dao.InvalidDataAccessApiUsageException: Executing an update/delete query; nested exception is javax.persistence.TransactionRequiredException: Executing an update/delete query] with root cause
javax.persistence.TransactionRequiredException: Executing an update/delete query
Когда я меняю управление транзакциями из AspectJ-режима
@EnableTransactionManagement(mode = AdviceMode.ASPECTJ)
Для режима прокси по умолчанию:
@EnableTransactionManagement
Исключение больше не возникает.
Вот методы в порядке вызова:
От MessageRestController
:
@RestController
...
@PatchMapping("mark-messages-as-read/{otherId}")
public void markMessagesAsRead(@CurrentUserAccount UserAccount me, @PathVariable Long otherId) {
UserAccount other = userAccountService.findUserAccountById(otherId);
messageService.markMessagesAsRead(me, other);
}
От MessageService
:
@Service
@Transactional
...
@Override
public void markMessagesAsRead(UserAccount me, UserAccount other) {
Assert.notNull(me);
Assert.notNull(other);
messageRepository.markMessagesAsRead(me, other);
}
От MessageRepository
:
@Modifying
@Query("update Message m set m.messageRead = true where m.recipient = :me and m.sender= :other")
void markMessagesAsRead(@Param("me") UserAccount me, @Param("other") UserAccount other);
Мне очень любопытно узнать, почему переключение из режима AspectJ в режим Proxy приводит к тому, что исключение больше не происходит.
Может кто-нибудь, пожалуйста, посоветуйте?
edit: вот декларация реализации сервиса:
@Service
@Transactional
public class MessageServiceImpl implements MessageService {
и из интерфейса сервиса:
void markMessagesAsRead(UserAccount me, UserAccount other);
1 ответ
Вы читали официальную документацию по использованию AspectJ?
Вы должны использовать AspectJ для этого, чтобы соткать код вашего приложения.
Конечно, с настройками по умолчанию это работает хорошо, так как Spring AOP создает прокси времени выполнения для ваших классов.