У меня есть расписание:
@Component
public class MyScheduler {
private static final long INIT_DELAY = 1L;
private static final long DELAY = 10L;
private final UserService userService;
public MyScheduler(UserService userService) {
this.userService = userService;
}
@EventListener(ApplicationReadyEvent.class)
public void schedule() {
ScheduledExecutorService scheduledExecutorService = Executors.newSingleThreadScheduledExecutor();
scheduledExecutorService.scheduleWithFixedDelay(this::process, INIT_DELAY, DELAY, TimeUnit.SECONDS);
}
private void process() {
userService.process(new User("Bill", 20));
}
}
В UserService я сохраняю нового пользователя и выбрасываю исключение:
@Slf4j
@Service
public class UserServiceImpl implements UserService {
private final UserRepository userRepository;
public UserServiceImpl(UserRepository userRepository) {
this.userRepository = userRepository;
}
@Override
public void process(User user) {
log.info("Start process...");
userRepository.save(user);
methodWithException();
log.info("End process...");
}
private void methodWithException() {
throw new RuntimeException();
}
}
В результате пользователь сохраняется, несмотря на исключение.Чтобы исправить это, я могу применить несколько способов:
1) Добавить @Transactional
выше private void process()
и изменить этот метод на public
2) Добавить @Transactional
выше public void process(User user)
методв UserService
В первом случае это не помогает, потому что process() witn @Transactional
вызывает из того же класса.
Во втором случае это помогает.
Но если я добавлю новую Службу, например LogService:
@Service
public class LogServiceImpl implements LogService {
private final LogRepository logRepository;
public LogServiceImpl(LogRepository logRepository) {
this.logRepository = logRepository;
}
@Transactional
@Override
public Log save(Log log) {
return logRepository.save(log);
}
}
И поменяю планировщик на:
@Component
public class MyScheduler {
private static final long INIT_DELAY = 1L;
private static final long DELAY = 10L;
private final UserService userService;
private final LogService logService;
public MyScheduler(UserService userService, LogService logService) {
this.userService = userService;
this.logService = logService;
}
@EventListener(ApplicationReadyEvent.class)
public void schedule() {
ScheduledExecutorService scheduledExecutorService = Executors.newSingleThreadScheduledExecutor();
scheduledExecutorService.scheduleWithFixedDelay(this::process, INIT_DELAY, DELAY, TimeUnit.SECONDS);
}
private void process() {
User user = userService.process(new User("Bill", 20));
logService.save(new Log(user.getId(), new Date()));
}
}
Вопрос :
userService.process
вызов в одной транзакции и logService.save
вызов в другой транзакции.Мне нужны вызовы в одной транзакции.
Я вижу два пути:
1) ввести logService
в userService
и вызвать logService.save
в userService.process
метод
2) Создайте новую службу, например SchedulerService
с методом process
, и введите userService
и logService
в эту службу.И звоните в оба сервиса за одну транзакцию.
В первом случае я получаю новую зависимость в userService
, и это может нарушить зону ответственности в этом сервисе.Почему служба должна знать, что нужно тянуть другую службу
Во втором случае мне нужно создать дополнительную службу (еще один класс)
Было бы идеально, если бы была возможность комментировать внутренний метод Schedulers @Transactional
аннотаций.Я знаю, что это можно сделать, используя cglib вместо прокси , но я использую прокси.
Какой подход будет лучше?