-----------------------------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
문제를 방지할 수 있었다.