조회수 증가 방지 (DB에서 처리)
- 비회원이거나 본인 글이면 조회수 증가를 방지하는 기능을 넣고자 한다. 이를 처리하기 위해서 서버에서 쿠키를 이용해서 구현할 수 있지만 정석으로는 DB에서 다뤄야하기 때문에 DB를 이용해서 처리한다.
DB
- Member, board 테이블은 M : N의 다대다 형식을 띄고 있다. 이를 해결하기 위해서는 다대일로 풀어줄 수 있는 중간 테이블이 필요하다. 이를 위해서
view_log
테이블을 생성하고 account, board_no를 외래키로 지정
-- 조회수 기록 관리 테이블
-- M : N 을 해결하기위해 중간 테이블 생성
CREATE TABLE view_log (
id INT PRIMARY KEY auto_increment,
account VARCHAR(50),
board_no INT,
view_time DATETIME
);
ALTER TABLE view_log
ADD CONSTRAINT fk_member_viewlog
FOREIGN KEY (account)
REFERENCES tbl_member (account);
ALTER TABLE view_log
ADD CONSTRAINT fk_board_viewlog
FOREIGN KEY (board_no)
REFERENCES tbl_board (board_no);
ViewLog
public class ViewLog {
private long id;
private String account;
private long boardNo;
private LocalDateTime viewTime;
}
ViewLogMapper
- 조회수 기록 시간 수정은 1시간이 지났으면 조회수가 또 오르게 하기 위해 만듦
ViewLogMapper.xml
<insert id="insertViewLog">
INSERT INTO view_log
(account, board_no, view_time)
VALUES
(#{account}, #{boardNo}, #{viewTime})
</insert>
<update id="updateViewLog">
UPDATE view_log
SET view_time = #{viewTime}
WHERE account = #{account}
AND board_no = #{boardNo}
</update>
<select id="findOne" resultType="viewLog">
SELECT *
FROM view_log
WHERE account = #{account}
AND board_no = #{bno}
</select>
BoardService
String currentUserAccount = getLoggedInUserAccount(session);
if (!isLoggedIn(session) || isMine(b.getAccount(), currentUserAccount)) {
return new BoardDetailResponseDto(b);
}
int boardNo = b.getBoardNo();
ViewLog viewLog = viewLogMapper.findOne(currentUserAccount, boardNo);
boolean shouldIncrease = false;
ViewLog viewLogEntity = ViewLog.builder()
.account(currentUserAccount)
.boardNo(boardNo)
.viewTime(LocalDateTime.now())
.build();
if (viewLog == null) {
viewLogMapper.insertViewLog(viewLogEntity);
shouldIncrease = true;
} else {
LocalDateTime oneHourAgo = LocalDateTime.now().minusHours(1);
if (viewLog.getViewTime().isBefore(oneHourAgo)) {
viewLogMapper.updateViewLog(viewLogEntity);
shouldIncrease = true;
}
}
if (shouldIncrease) {
boardMapper.upViewCount(boardNo);
}
return new BoardDetailResponseDto(b);
}