api를 만들 때 하나의 값을 반환하는 것이 아니라 여러 값들을 반환할 상황이 여럿있다.
하지만 Dto와 builder pattern을 사용할 때 어떻게 사용해야할지 막막할 수 있다.
일단 List로 반환해야하는 상황을 가지고 있는 api를 만들어보자.
@RequiredArgsConstructor
@RestController
@RequestMapping("/api/v1/posts")
public class PostsApiController {
private final PostsService postsService;
@GetMapping("/find/{title}")
public Result findByTitle(@PathVariable String title){
List<PostsResponseDto> all = postsService.findByTitle(title);
return new Result(all);
}
}
위의 api는 제목으로 검색하여 조회하는 api이다. 같은 제목인 게시물이 여러개 있을 수 있으니 List로 반환 해주어야 한다.
@Getter
@AllArgsConstructor
@Builder
public class PostsResponseDto {
private Long id;
private String title;
private String content;
private String author;
}
public interface PostsRepository extends JpaRepository<Posts, Long> {
List<Posts> findByTitle(String title);
}
@Service
@RequiredArgsConstructor
@Transactional(readOnly = true)
public class PostsService {
private final PostsRepository postsRepository;
public List<PostsResponseDto> findByTitle(String title){
List<Posts> all = postsRepository.findByTitle(title); // 1
List<PostsResponseDto> postsResponseDtoList = new ArrayList<>(); // 2
for(Posts posts : all){ // 3
PostsResponseDto dto = PostsResponseDto.builder()
.id(posts.getId())
.title(posts.getTitle())
.author(posts.getAuthor())
.content(posts.getContent())
.build();
postsResponseDtoList.add(dto); // 4
}
return postsResponseDtoList;
}
}
1 : 사용자에게 입력 받은 제목을 가진 게시물을 모두 조회한다.
2 : 반환 값이 List이기 때문에 PostsResponseDto도 List로 생성해준다.
3 : 타입이 Posts인 참조변수 posts에 1번에서 조회한 게시물들을 하나씩 PostsResponseDto에 저장한다.
4 : 3번에서 저장한 데이터가 담겨 있는 참조 변수 dto를 2에 add한다.
public List<FreePostsCreateResponseDto> findByTitle(String title){
return freePostsRepository.findByTitle(title).stream()
.map(FreePostsCreateResponseDto::new)
.collect(Collectors.toList());
PostsApiController에서 값을 반환할 때 List 타입을 그냥 반환하지 않고 제네릭 타입의 클래스를 하나 만들고 그 클래스를 통해서 반환해 주는 것이 더 좋다.(코드 유연성 ⬆)
@Data
@AllArgsConstructor
public class Result<T> {
private T data;
}