Могу ли я прямо обратиться к репозиторию Entity A из Service B?
Да, можно. Другой вопрос - хорошо ли.
Или мне надо это делать вот так Service B -> Service A -> Repository A?
Я предпочитаю этот способ.
Причина следующая:
Вот, представьте, что на сервисном уровне вы получаете
Optional<T>
из репозитория и в случае, если объект не найден, то на сервисном уровне выбрасываете исключение
orElseThrow()
. Ну а далее ExceptionHandler ловит исключение и отдает соответствующий код ошибки и сообщение на фронт.
Если вы решите из сервиса А обратиться в репозиторий Б, то по факту вам нужно заново получить объект и выбросить исключение в случае, если он не найден, а это уже дублирование кода...
Псевдокод:
ServiceA {
@Autowired
RepoB repoB;
@Autowired
ServiceB serviceB;
// 1 вариант
List<Job> doSomeJob1(String email){
User user = repoB.findUserByEmail(email).orElseThrow(UserNotFoundException::new);
return user.getJobs();
}
// 2 вариант
List<Job> doSomeJob2(String email) {
User user = serviceB.getUserByEmail(email);
return user.getJobs();
}
RepoB {
Optional<User> findUserByEmail(String email);
}
ServiceB {
@Autowired
RepoB repoB;
User getUserByEmail(String email){
return repoB.findUserByEmail(email).orElseThrow(UserNotFoundException::new);
}
}
Во втором варианте нам не пришлось писать логику и выбрасывать исключение.
А так многое зависит от проекта, от того, как принято в команде работать и т.д.
Проблема в том, что у меня все сервисы DTOшки, а для работы Service B нужны нормальные объекты, что делать в таком случае? Неужели создавать отдельные точно такие же методы просто без конверта в дто?
Я это обычно, делаю по другому. Я возвращаю объекты из сервисов. А если мне нужно DTO, то есть отдельный сервис MapperService, который принимимает дженерик и возвращает соответствующие DTO.