Каким образом можно отрефакторить метод getAllProjects() в реализации сервиса?
У меня есть следующий сервис с реализацией внутри проекта:
@Service
public class ProjectServiceImpl implements ProjectService {
@Autowired
private ProjectRepository projectRepository;
@Autowired
private ProjectAdaptor projectAdaptor;
@Override
public List<Project> getAll() {
return projectRepository.findAll();
}
@Override
public List<Project> getAllProjects(Long companyId) {
return projectRepository.getAll().stream()
.filter(project -> project.getId() == companyId).findAny().orElse(null);
}
@Override
public Project save(Project project) {
return projectRepository.save(project);
}
@Override
public List<ProjectDTO> findAllProducts() {
List<Project> project = projectRepository.findAll();
return projectAdaptor.databaseModelToUiDtoList(project);
}
}
В котором есть метод getAll():
@Override
public List<Project> getAll() {
return projectRepository.findAll();
}
и соответственно к нему getAllProjects():
@Override
public List<Project> getAllProjects(Long companyId) {
return projectRepository
.getAll()
.stream()
.filter(project -> project.getId() == companyId)
.findAny()
.orElse(null);
}
В связи с этим вопрос, каким образом отрефакторить вышепоказанный метод, который воспроизводит ошибку компиляции, связанную с типом Object:
Cannot resolve method
getIdinObject.
Моя сущность Project имеет следующую структуру:
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
@Entity(name = "project_entity")
@Table(name = "projects")
public class Project {
public Project(ProjectDTO projectDTO) {
this.name = projectDTO.getName();
this.abbreviation = projectDTO.getAbbreviation();
this.customer = projectDTO.getCustomer();
}
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "project_id")
private Integer id;
private String name;
private String abbreviation;
private String customer;
}
Нужно ли мне добавлять дополнительные аннотации Lombok над сущностью, чтобы решить данную проблему или есть способ просто объединить два метода в один в более правильном виде?
Буду очень благодарен за помощь по данному вопросу.
Ответы (2 шт):
Хочу заметить еще, что не хорошая практика возвращать null, можно это все обернуть в Optional<T>, и еще findAny() в методе getAllProjects() подразумевает возвращение одного значения из стрима в обертке Optional, но Ваш метод возвращает List<Project>.
Для того, чтобы избежать описанной Вами проблемы:
Замените
getAll()в вызове наfindAll(). Данный метод возвращает список объектовProjectвместоObject.Или приводите к типу
Projectв лямбда-выражении.filter(((Project)project) -> project.getId() == companyId)
Разумеется, первый подход предпочтительнее. Отметьте мой ответ, если он помог Вам.
Советую вам ещё раз хорошо подумать - стоит ли делать фильтрацию в памяти. Если у вас есть строгие гарантии что
projectRepository.findAll()никогда не вернет большое кол-во объектов и будет вызываться редко - то Ваш подход с фильтрацией в памяти с использованием Stream уместен. Иначе, создайте в репозитории отдельный метод, который умел бы фильтровать проекты по companyId и вызывайте внутри сервиса именно его (или можно сделать на уровне репозитоиря метод, который принимает универсальный фильтр, например, через Criteria API).Ещё один важный момент - если ваш метод возвращает список, то он никогда не должен возвращать null. Это очень плохая практика. Если у вас нет объектов - просто верните пустой список.
Непонятно, чем различаются методы
projectRepository.findAll()иprojectRepository.getAll(). Исходя из их названия напрашивается вывод, что они делают одно и тоже. В таком случае у вас дублирование кода. Если они делают разные вещи - то переименуйте один из методов так, чтобы это было сразу понятно.Транзакции желательно делать на уровен сервиса.
Соблюдайте последовательность в наименовании методов. Если на уровне репозитория метод называется findAll(), то и на уровне сервиса его метод-обертка должен называться точно также.
