TIL 23.02.11

쓰옹·2023년 2월 12일
0

개발자를 향해~~TIL✍

목록 보기
84/87

사용자가 참여하고 있는 그룹의 목록을 조회할 떄

// GroupServiceImpl.java
public List<MyGroupResponseDto> getMyGroupsByLeader(Long userId) {
		List<Group> groups = groupRepository.findAllByUserIdOrderByCreatedAtDesc(userId);
		List<MyGroupResponseDto> myGroupResponseDtoList = new ArrayList<>();

		for (Group group : groups) {
			List<Participant> participants = participantRepository.findAllByGroupIdOrderByCreatedAtDesc(
				group.getId()); 
			List<ParticipantResponseDto> participantResponseDtoList = new ArrayList<>();
			for (Participant participant : participants) {
				participantResponseDtoList.add(new ParticipantResponseDto(participant));
			}
			myGroupResponseDtoList.add(new MyGroupResponseDto(group, participantResponseDtoList));
		}
		return myGroupResponseDtoList;
}

처음에 작성을 하고 이중 for문에 집중에서 수정으로 하려고 했는데 정작 문제는 다른 데 있었다. for문 안에서 repository를 조회하면 for문을 한 번 돌 때마다 쿼리가 계속 날라가게 되므로 서버가 터질 수 있는 문제점이 있다. 그래서 jpql로 그룹 id와 연결된 참여자의 리스트를 찾는 쿼리를 짜고 그걸 이용해서 수정을 했다. 페치 조인을 사용하면 연관된 엔티티를 한 번의 쿼리로 모두 가져올 수 있다. 그리고 쿼리가 n+1로 날라갈 수 있는걸 해결한다.
쿼리를 직접 짜서 for문에서 뺄 수 있고 훨씬 적은 수의 쿼리로 조회할 수 있게 되었다.

// ParticipantRepository.java
public interface ParticipantRepository extends JpaRepository<Participant, Long> {
	@Query(value = "select p from Participant p join fetch p.group where p.group.id in (:groupIdList)")
	List<Participant> findAllParticipants(@Param("groupIdList") List<Long> groupIdList);

}

// GroupServiceImpl.java
public List<MyGroupResponseDto> getMyGroupsByLeader(Long userId) {

		List<MyGroupResponseDto> myGroupResponseDtoList = new ArrayList<>();

		List<Group> groups = groupRepository.findAllByUserIdOrderByCreatedAtDesc(userId);
		List<Long> groupIdList = groups
			.stream()
			.map(Group::getId)
			.toList();

		List<Participant> participants = participantRepository.findAllParticipants(groupIdList);

		for (Group group : groups) {
			List<ParticipantResponseDto> participantResponseDtoList = participants.stream()
				.filter(p -> p.getGroup().getId().equals(group.getId()))
				.map(Participant::toParticipantResponseDto)
				.toList();
			myGroupResponseDtoList.add(new MyGroupResponseDto(group, participantResponseDtoList));
		}

		return myGroupResponseDtoList;
}

처음에 로직을 구성할 때 쿼리가 얼마나 날라가는지에 대한 생각도 필요한 것 같다. 그걸 모두 고려해서 작성해야한다. jpa공부가 더 필요하다. 다른분들의 도움을 받아 작성했지만 아직 스트림에 대한 개념도 부족하기 떄문에 갈 길이 멀다..

위에서 쓴 스트림을 for문으로 바꿔보았당


List<ParticipantResponseDto> dtoList = new ArrayList<>();
for (Participant p : participants) {
	if (p.getGroupId().equals(group.getId()) {
		dtoList.add(new ParticipantResponseDto(p));
	}
}
profile
기록하자기록해!

0개의 댓글