[토이 투표] 22.07.07 일지

재호·2022년 7월 7일
0

22.07.07 개발 일지

메인 화면 팔로잉 투표

-----------------------------Main Controller-------------------------------
	@Transactional
	@RequestMapping("/")
	public String home(HttpSession session, Model model) {
		log.info("mainpage 요청");
		//투표 마감여부 체크
		boardService.checkClose();
		//인기글 가져오기
		List<BoardDTO> list = boardService.mostPopluar();
		//팔로우 정보 가져오기
		String sessionLogin = (String)session.getAttribute("userLogin");
		if(sessionLogin != null) {
			List<BoardDTO> boardByFollow =  boardService.getFollowerLatest((String)session.getAttribute("userId"));
			model.addAttribute("fBoard", boardByFollow);
		}
		model.addAttribute("list", list);
		return "index";
	}
-----------------------------Board Service-------------------------------
	@Override //팔로워 최근 게시글
	public List<BoardDTO> getFollowerLatest(String email) {
		Pageable pageable = PageRequest.of(0, 3);
		List<Board> list = boardRepository.getLatestFollow(email, pageable);
		
		List<BoardDTO> result = new ArrayList<>();
		for(Board board : list) {
			BoardDTO dto = entityToDto(board, 0);
			result.add(dto);
		}
		return result;
	}
-----------------------------Board Repository-------------------------------
	@Query("select b from Board b join fetch b.member m join fetch m.follows f where f.me = :me order by b.bno desc")
	List<Board> getLatestFollow(@Param("me") String me, Pageable pageable);

로그인 유저가 팔로우 중인 유저들의 게시글을들을 최신순으로 정렬하고 그 중 3개의 글만 가져오도록 쿼리를 짜고 출력되도록 했다.

전체 팔로잉 게시글


전체적인 폼은 기본 리스트와 같고 출력되는 데이터만 팔로우 기준이다.

-----------------------------Board Controller-------------------------------
	@GetMapping("/follow")
	public void followBoardList(String me, PageRequestBoardDTO dto, Model model) {
		log.info("팔로우 리스트 요청");

		if(dto == null) {
			dto = new PageRequestBoardDTO();
		}
		
		dto.setKeyword(me);
		
		PageResponseBoardDTO response = boardService.getListofFollow(dto);
		model.addAttribute("list", response.getBoardList());
		model.addAttribute("page", response);
	}
    
-----------------------------Board Service-------------------------------
	@Override
	public PageResponseBoardDTO getListofFollow(PageRequestBoardDTO dto) {
		Sort sort= Sort.by("bno").descending();
		Pageable pageable = PageRequest.of(dto.getPage()-1, dto.getSize(), sort);
		Page<Board> page = boardRepository.boardByFollow(dto);
		
		PageResponseBoardDTO result = new PageResponseBoardDTO();
		result.setTotalPage(page.getTotalPages());
		result.makePageList(pageable);
		List<BoardDTO> list = new ArrayList<>();
		page.get().forEach(item -> {
			list.add(entityToDto(item, 0));
		});
		result.setBoardList(list);
		return result;
	}
    
-----------------------------Board Custom Repository--------------------------
	@Override
	public Page<Board> boardByFollow(PageRequestBoardDTO dto) {
		int page = dto.getPage()-1;
		int size = dto.getSize();
		
		List<Board> list = query.selectFrom(board)
								.join(board.member, member)
								.fetchJoin()
								.join(member.follows, follow)
								.fetchJoin()
								.where(containFollow(dto.getKeyword()))
								.orderBy(board.bno.desc())
								.offset(page*size)
								.limit(size)
								.fetch();
		
		long count = query.selectFrom(board)
						.join(board.member, member)
						.fetchJoin()
						.join(member.follows, follow)
						.fetchJoin()
						.where(containFollow(dto.getKeyword()))
						.orderBy(board.bno.desc())
						.offset(page*size)
						.limit(size)
						.fetchCount();
		
		Sort sort = Sort.by("bno").descending();
		Pageable pageable = PageRequest.of(dto.getPage()-1, dto.getSize(), sort);
		
		return new PageImpl<>(list, pageable, count);
	}
	
	private BooleanExpression containFollow(String email) {
		return follow.me.eq(email);
	}

board -> member-> follow 3개의 테이블의 조인이 필요해서 JQPL을 이용했고 순수 JPQL만으로는 Fetch Join 시에 페이징을 할 수 없기 때문에 QueryDSL을 사용했다.

개인 메뉴


상단 네비의 내 정보 버튼을 눌렀을 때 바로 회원정보 페이지가 출력되도록 했었지만 여러 페이지로 이동할 수 있는 메뉴 페이지를 새로 만들었다. 기존 마이페이지는 회원 정보 버튼을 통해 들어갈 수 있다.

-----------------------------Member Controller-------------------------------
	//메뉴이동
	@GetMapping("/menu")
	public void menu() {
		log.info("menu 이동");
	}

팔로워, 팔로잉 목록


메뉴의 팔로우 버튼을 통해 이동할 수 있다. 팔로워 목록과 팔로우 목록을 동시에 출력하도록 했다.

-----------------------------Member Controller-------------------------------
	//팔로우 메뉴
	@GetMapping("/follow")
	public void follow(HttpSession session, Model model) {
		log.info("follow 목록 요청");
		String email = (String)session.getAttribute("userId");
		
		List<FollowDTO> follower = memberService.getFollower(email);
		List<FollowDTO> following = memberService.getFollowing(email);
		
		model.addAttribute("followerList", follower);
		model.addAttribute("followingList", following);
	}
    
-----------------------------Member Service-------------------------------
	@Override
	public List<FollowDTO> getFollower(String email) {
		Member member = memberRepository.findByEmail(email).get(0);
		List<Follow> list = followRepository.findByFmember(member);
		
		List<FollowDTO> result = new ArrayList<>();
		for(Follow follow : list) {
			FollowDTO dto = FollowDTO.builder().fno(follow.getFno())
											.me(follow.getMe())
											.youEmail(email).build();
			result.add(dto);
		}
		return result;
	}
	
	@Override
	public List<FollowDTO> getFollowing(String email) {
		List<Follow> list = followRepository.findByMe(email);
		
		List<FollowDTO> result = new ArrayList<>();
		for(Follow follow : list) {
			FollowDTO dto = FollowDTO.builder().fno(follow.getFno())
											.me(email)
											.youEmail(follow.getFmember().getEmail()).build();
			result.add(dto);
		}
		return result;
	}

-----------------------------Follow Repository-------------------------------
	//팔로잉 목록 가져오기
	@EntityGraph(attributePaths = {"fmember"})
	List<Follow> findByMe(String me);
	
	//팔로워 목록 가져오기
	List<Follow> findByFmember(Member fmember);

팔로잉 목록을 조회할 때에는 @EntityGraph를 통해 join 조회가 되도록 했다. 그 덕분에 서비스단에서 엔티티를 dto로 변환하여 저장할 때 추가 쿼리가 발생하는 n+1문제를 방지할 수 있었다.

Git

https://github.com/JINJAEHO/vote

profile
Java, Spring, SpringMVC, JPA, MyBatis

0개의 댓글