@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 속성을 하나 추가하였다.