@Modifying
@Query("update Board p set p.count = p.count +1 where p.id = :id")
int updateView(Long id);
// update Board p : 수정할 엔터티는 Board 이고 p 라고 칭합니다.
// set p.count = p.count + 1 : 엔터티 p의 count 속성을 1 증가 시킵니다.
// where p.id = :id : 해당 게시글의 id와 일치하는 레코드에만 조회수를 증가 시킵니다.
Optional<Board> board = boardRepository.findById(id); // ID를 사용하여 게시글을 조회합니다. 게시글이 존재하면 Optional로 감싸진 게시글 객체를 반환합니다.
if (board.isPresent()) { //isPresent() 메서드는 Optional 객체 안에 값이 존재하는지 여부를 반환합니다.
Board boardEntity = board.get(); // Optional 객체 안에 존재하는 게시글 객체를 가져옵니다.
boardEntity.incrementViewCount(); // 게시글의 조회수를 증가시킵니다. (incrementViewCount()는 엔터티에 정의된 메서드이며 조회수를 1 증가시키는 역할을 합니다.)
boardRepository.save(boardEntity); // 조회수 정보를 저장합니다.
} else {
throw new EntityNotFoundException("게시글을 찾을 수 없습니다." + id);
}
}
Set<Long> viewedPosts = Optional.ofNullable((Set<Long>) session.getAttribute("viewedPosts")).orElse(Collections.emptySet());// 속성을 가져오는 부분은 추후에 해당 속성을 업데이트 하거나 사용할 때 유용하게 활용될 수 있도록 준비하는 단계입니다.
//세션에서 viewedPosts 속성을 가져옵니다. Optional.ofNullable()은 가져온 속성이 null인지 확인하고, 그렇지 않은 경우에만 Optional 객체를 생성합니다. 가져온 속성을 set<Long> 타입으로 형변환 합니다.
//.orElase(Collections.emptySet()) 가져온 속성이 null인 경우에는 빈 Set을 반환합니다. null 체크를 통해서 NullPointException을 방지합니다.
return viewedPosts.contains(id); // 형변환된 조회한 게시글 집합에 지정된 ID가 포함되어 있는지 확인하고, 그 결과를 반환합니다.
}
if(viewedPosts == null) { // viewed 속성이 null 이라면
viewedPosts = new HashSet<>(); // 새로운 HashSet을 생성하여 조회한 게시글의 ID를 관리할 준비를 합니다.
}
viewedPosts.add(id); // 조회한 게시글의 ID를 viewedPosts 속성에 추가합니다.
session.setAttribute("viewedPosts", viewedPosts); // 세션에 있는 viewedPosts 속성을 업데이트 합니다.
}
if(!hasViewedPost(id)){ //해당 게시글이 이미 조회되었는지 확인합니다.
BoardDetail(id); //해당 게시글이 조회되지 않았으면 게시글의 조회수를 증가시킵니다.
addViewedPostToSession(id); //조회된 게시물 ID를 세션에 기록하여 중복 조회를 방지합니다.
}
return getPostDetail(id);
}
@Column(columnDefinition = "integer default 0", nullable = false)
private Long viewCount=0L; //조회수를 저장하는 컬럼입니다. 기본값을 0으로 설정합니다.
public void incrementViewCount(){ //조회수를 증가시키는 메서드입니다.
this.viewCount++; // 조회수를 1 증가시킵니다.
}
사용자가 동일한 세션에서 여러 번 페이지를 조회 해도 조회수가 증가하지 않습니다. (중복제거)
세션 데이터가 서버 메모리에 저장되어 중복 조회를 필터링 할 수 있습니다.
하지만 동시에 많은 사용자가 접속하는 경우 서버 부하가 증가 할 수 있기 때문에
외부 스토리지에 저장하는 것을 권장한다고 합니다.
현재는 로컬에서 공부하는 용도이기 때문에 추후에 데이터베이스에 저장하는 것을 구현해볼 생각입니다.
분산 파일 시스템
클라우드 스토리지 서비스
캐시 서버
데이터베이스 서비스