[토이 투표] 개발일지(22.07.01)

재호·2022년 7월 1일
0

22.07.01 일지

글 등록 수정(투표 항목 추가)

	@Override // 투표글 등록
	public Long registerBoard(BoardDTO boardDTO, List<VoteItemDTO> itemDTO) {
		//마감 시간을 설정하지 않았다면 24시간을 기본값으로 설정
		if(boardDTO.getClosetime() == null) {
			ZonedDateTime nowUTC = ZonedDateTime.now(ZoneId.of("UTC"));
			LocalDateTime currentDateTime = nowUTC.withZoneSameInstant(
											ZoneId.of("Asia/Seoul")).toLocalDateTime();
			LocalDateTime closetime = currentDateTime.plusHours(24);
			boardDTO.setClosetime(closetime);
		}

		// Board 정보 DB에 저장
		Board board = dtoToEntity(boardDTO);
		boardRepository.save(board);

		// 투표 항목들 리스트로 변환 후 한번에 DB에 저장
		List<VoteItem> list = new ArrayList<>();
		for(VoteItemDTO dto : itemDTO) {
			VoteItem item = VoteItem.builder().item(dto.getItem())
												.imageurl(dto.getImageurl())
												.board(board).build();
			list.add(item);
		}
		itemRepository.saveAll(list);

		return board.getBno();
	}

글을 등록할 때 기존에는 글의 제목이나 내용만 등록했었지만 투표 항목의 엔티티들도 같이 저장되도록 수정했다. 투표 항목은 한개 이상이 나오기 때문에 하나씩 저장하지 않고 리스트로 모았다가 saveALl을 통해 한번에 저장하면서 쓸데없는 통신 과정을 줄여보았다.

글 상세 정보 수정(투표 항목 함께 조회)

	@EntityGraph(attributePaths = {"member", "items"})
	@Query(value =  "select b from Board b where b.bno = :bno",
			countQuery = "select count(b) from Board b where b.bno = :bno")
	public Optional<Board> findByIdWithJoin(@Param("bno") Long id);



	@Override //글 정보 가져오기
	public BoardDTO getBoard(BoardDTO dto) {
		Long bno = dto.getBno();
		Optional<Board> optional = boardRepository.findByIdWithJoin(bno);
		//글이 존재한다면
		if(optional.isPresent()) { 
			return entityToDto(optional.get());
		}
		return null;
	}

기존에 글 상세 정보를 가져올 때는 위의 글 등록과 마찬가지로 투표 내용이 빠졌었는데 이번에 추가하면서 findByIdWithJoin 메서드를 만들어 Member 엔티티와 VoteItem 엔티티를 fetch join하도록 했다.

글 수정

	@Override //글 수정
	public Long updateBoard(BoardDTO dto) {
		Board findBoard = boardRepository.findById(dto.getBno()).get();
		findBoard.changeBoard(dto.getTitle(), dto.getDescription(), dto.getClosetime());
		return dto.getBno();
	}

기존 글 수정은 save 메서드를 이용했지만 이전 글에서 설명했듯이 효율이 좋지 않아 더티 체킹 방식으로 수정했다.

또한 글 수정 시 투표 항목에 대한 수정은 특정 조건 하에만 가능하도록 했다.
만약 1명이라도 해당 투표에 참여했다면 투표의 공정성을 위해 투표 항목에 대한 수정은 불가능 하도록 한 것이다.

투표 항목에 대한 수정 가능 여부를 체크하는 메서드는 ItemService 클래스에 구현했다.

  public interface VoteDetailRepository extends JpaRepository<VoteDetail, Long> {
      long countByVoteitem(VoteItem voteitem);
  }




	@Override // 투표 항목 수정 가능 여부 체크
	public int canModify(List<Long> itemIdList) {
		boolean canModifyItem = false;
		// 한명 이상이 투표를 실시했다면 수정을 불가능 하도록 설정
		for(Long id : itemIdList) {
			VoteItem voteItem = itemRepository.findById(id).get();
			long count = detailRepository.countByVoteitem(voteItem);
			// 수정 불가능
			if(count > 0) {
				canModifyItem = false;
				break;
			// 수정 가능
			}else canModifyItem = true;
		}
		
		if(canModifyItem) return 1;
		
		return 0;
	}

투표 항목 수정 메서드 추가

위의 과정에서 투표 항목의 수정이 가능하다고 판단되었다면 수정할 수 있도록 메서드를 만들었다.
메서드는 ItemService 클래스에 구현했다.

	@Override //투표 항목 수정 및 추가
	public void itemUpdate(List<VoteItemDTO> itemDTO) {
		List<VoteItem> list = new ArrayList<>();
		for(VoteItemDTO dto : itemDTO) {
			VoteItem item = dtoToEntity(dto);
			list.add(item);
		}
		// 투표 항목은 수정뿐 아니라 추가도 가능하므로 save로 업데이트 한다
		itemRepository.saveAll(list);
	}

지금까지 수정 메서드에를 전부 save에서 더티 체킹 방식으로 변경하였는데, 이번에는 save를 이용하기로 했다. 그 이유는 투표 항목은 수정만이 아니라 추가도 가능하기 때문에 새로운 항목이 추가될 때는 더티 체킹만으로는 할 수 없기 때문이다.

실제 투표 처리

	@Override //실제 투표 처리
	public String throwVote(VoteItemDTO itemDTO, String email) {
		VoteItem item = dtoToEntity(itemDTO);
		VoteDetail detail = VoteDetail.builder().voter(email)
											.voteitem(item)
											.build();
		VoteDetail result = detailRepository.save(detail);
		if(result != null) return "성공";
		return "실패";
	}

사용자가 실제로 투표를 했을 때 VoteDetail 테이블에 데이터가 저장되는 메서드를 구현했다. 만약 익명 투표라면 email 파라미터에는 'anonymous'가 입력되도록 Controller 레벨에서 처리할 것이다.

투표 항목 테이블 수정

글의 상세 내용을 조회했을 때 투표 항목 뿐만 아니라 몇 명의 인원이 각각의 항목에 투표하였는지, 즉 각 항목의 득표 수를 편하게 얻기 위해서 VoteItem(투표항목) 테이블에 count 속성을 하나 추가하였다.

Git

https://github.com/JINJAEHO/VoteProject

profile
Java, Spring, SpringMVC, JPA, MyBatis

0개의 댓글