Hibernate получить список по условию, иначе вернуть все сущности в списке
Пусть есть сущность User:(для простоты имеет 2 поля)
@Entity
@Builder
@Getter
@Setter
@AllArgsConstructor
@NoArgsConstructor
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;
@Column(nullable = false)
private String name;
Есть слой репозитория:
@Repository
public interface UserRepository extends JpaRepository<User, Integer> {
Optional<User> findUserByName(String userName);
List<User> findUserByNameContaining(String fragment);
Имеется контроллер, с двумя эндпоинтами:
@GetMapping("/all")
public List<User>getAllUsers(){
return userService.findAll();
}
@GetMapping("/all{nameFragment}")
public List<User>getAllUsers( @PathVariable(name = "nameFragment") String nameFragment){
return userService.findUserByNameContaining(nameFragment);
}
Могу ли я как нибудь объединить два этих эндпоинта в один в метод
@GetMapping("/all{nameFragment}")
public List<User>getAllUsers( @PathVariable(name = "nameFragment") String nameFragment){
return userService.findUserByNameContaining(nameFragment);
}
И в зависимости от того, передал ли я аргумент nameFragment или нет, будет выполнять поиск либо пользователя, содержащего в себе часть nameFragment или в случае, если nameFragment=nullбудет выводиться все пользователи
т.е можно ли создать примерно такой метод в репозитории:
findUserByNameContainingElseFindAll(String nameFragment)
Или данную логику поведения нужно отдельно обрабатывать в сервисном слое ?
Ответы (1 шт):
Для "объединения" эндпойнтов в контроллере достаточно указать, что параметр запроса является необязательным required = false (также следует добавить / для разграничения параметра):
// контроллер
@GetMapping("/all/{nameFragment}")
public List<User>getAllUsers(
@PathVariable(name = "nameFragment", required = false) String nameFragment
) {
userService.findUserByNameContaining(nameFragment);
}
На уровне сервиса можно либо вызвать соответствующий метод существующего репозитория после проверки параметра на null:
// сервис
@Autowired
private UserRepository userRepo;
public List<User> findUserByNameContaining(String nameFragment) {
return null == nameFragment
? userRepo.findAll()
: userRepo.findUserByNameContaining(nameFragment);
}
Можно также написать кастомный запрос в репозитории и вызвать этот метод из сервиса напрямую, для использования LIKE придётся использовать JPQL-функцию CONCAT:
// репо
@Repository
public interface UserRepository extends JpaRepository<User, Integer> {
@Query("SELECT u FROM User u WHERE (?1 IS NULL OR u.name LIKE CONCAT('%', CONCAT(?1, '%')))")
List<User> findUserByNameContaining(String fragment);
}