일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | ||||
4 | 5 | 6 | 7 | 8 | 9 | 10 |
11 | 12 | 13 | 14 | 15 | 16 | 17 |
18 | 19 | 20 | 21 | 22 | 23 | 24 |
25 | 26 | 27 | 28 | 29 | 30 | 31 |
- 가상 면접 사례로 배우는 대규모 시스템 설계 기초
- JPA
- Spring Boot
- 정보처리기사
- 영속성 컨텍스트
- Redis
- 호이스팅
- 자바의 정석
- 게시판
- 분할정복
- sqld
- MongoDB
- 깃허브
- 다이나믹프로그래밍
- 스프링부트
- 캐시
- VMware
- in-memory
- 동적계획법
- document database
- 스프링 부트
- 정처기
- 스프링 시큐리티
- 실행 컨텍스트
- SQL
- github
- 레디스
- 이벤트루프
- spring security
- NoSQL
- Today
- Total
FreeHand
[Spring Boot] 게시판 프로젝트 - 05. 댓글 기능 본문
이전 글
[Spring Boot] 게시판 프로젝트 - 04. 회원정보 수정
이전 글 [Spring Boot] 게시판 프로젝트 - 03. 게시판 글 CRUD이전 글 { this.save(); }); }, save: function() { let d" data-og-host="pressky99.tistory.com" data-og-source-url="https://pressky99.tistory.com/39" data-og-url="https://pressky99.ti
pressky99.tistory.com
목차
1. 댓글 작성
2. 댓글 삭제
1. 댓글 작성
[detail.jsp]
... 생략 ...
<div class="card">
<form>
<input type="hidden" id="board-id" value="${board.id}"/>
<div class="card-body">
<textarea id="comment-content" class="form-control" rows="1"></textarea>
</div>
<div class="card-footer">
<button type="button" id="btn-comment-save" class="btn btn-primary">등록</button>
</div>
</form>
</div>
<br/>
<div class="card">
<div class="card-header">댓글</div>
<ul id="comment--box" class="list-group">
<c:forEach var="comment" items="${board.comments}">
<li id="comment--${comment.id}" class="list-group-item d-flex justify-content-between">
<div>${comment.content}</div>
<div class="d-flex">
<div class="font-italic">작성자: ${comment.user.username} </div>
<c:if test="${comment.user.id == principal.user.id}">
<button class="badge">삭제</button>
</c:if>
</div>
</li>
</c:forEach>
</ul>
</div>
</div>
<!-- Form end -->
<script src="/js/board.js"></script>
[board.js]
let index = {
init: function() {
// 생략
$("#btn-comment-save").on("click", () => {
this.commentSave();
});
}
commentSave: function() {
let data = {
board: {
id: $("#board-id").val()
},
content: $("#comment-content").val()
}
$.ajax({
type: "POST",
url: "/api/board/comment",
data: JSON.stringify(data),
contentType: "application/json; charset=utf-8",
dataType: "json"
}).done(function() {
alert("댓글 작성 완료");
location.reload(true);
}).fail(function(error) {
alert(JSON.stringify(error));
});
},
}
index.init();
글 상세 페이지에서 댓글 폼에 댓글을 입력하여 ajax 요청을 보내면 댓글이 등록된다.
@AllArgsConstructor
@NoArgsConstructor
@Getter @Setter @ToString
@Builder
@Entity
@Table(name = "comments")
public class Comment {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(nullable = false, length = 200)
private String content;
@ManyToOne
@JoinColumn(name = "boardId")
private Board board;
@ManyToOne
@JoinColumn(name = "userId")
private User user;
@CreationTimestamp
private Timestamp createdAt;
}
Comment와 Board 그리고 Comment와 User의 연관관계에서 Comment가 연관관계의 주인이기때문에 Comment를 save할 때 Board와 User를 초기화 해서 save해야 한다.
이렇게 해야 해당 댓글의 작성자와 어떤 글에 달린 댓글인지를 알수있다.
@RequiredArgsConstructor
@RestController
public class BoardApiController {
private final BoardService boardService;
// 생략
@PostMapping("/api/board/comment")
public ResponseEntity<Integer> saveComment(@RequestBody Comment comment,
@AuthenticationPrincipal PrincipalDetail principal) {
boardService.saveComment(comment, principal.getUser());
return new ResponseEntity<>(1, HttpStatus.CREATED);
}
}
@RequiredArgsConstructor
@Service
public class BoardService {
private final BoardRepository boardRepository;
private final CommentRepository commentRepository;
// 생략
@Transactional
public void saveComment(Comment comment, User user) {
Board board = boardRepository.findById(comment.getBoard().getId())
.orElseThrow(() -> new NoSuchElementException("댓글 작성 실패: 해당 글을 찾을 수 없음."));
comment.setBoard(board);
comment.setUser(user);
commentRepository.save(comment);
}
}
요청이 들어온 board의 id로 board를 초기화하고 로그인된 사용자로 작성자(User)를 초기화 해서 저장한다.
작성된 댓글은 해당 글의 상세 페이지에서 볼 수 있다.
@AllArgsConstructor
@NoArgsConstructor
@Getter @Setter
@Builder
@Entity
@Table(name = "boards")
public class Board {
// 생략
@OrderBy("createdAt")
@OneToMany(mappedBy = "board", fetch = FetchType.EAGER, cascade = CascadeType.REMOVE)
private List<Comment> comments = new ArrayList<>();
}
글 상세 페이지를 불러올때 댓글 목록이 바로 보이므로 댓글 리스트를 바로 조회하기 위해 FetcyType은 EAGER로 작성했다.
Board가 Comment 리스트를 갖고 있기 때문에 댓글을 조회하는 메서드는 필요없다. jsp에서 모델로 받은 board에서 comments를 바로 보여주면 댓글 목록이 보인다.
그리고 글을 삭제할때 댓글도 같이 삭제되도록 CascadeType은 REMOVE로 설정했다. 이 설정이 되어있지 않으면 글을 삭제할 때 외래키 cascade 때문에 에러가 발생한다.
2. 댓글 삭제
<c:if test="${comment.user.id == principal.user.id}">
<button onClick="index.commentDelete(${comment.id})" class="badge">삭제</button>
</c:if>
commentDelete: function(commentId) {
$.ajax({
type: "DELETE",
url: "/api/board/comment/" + commentId,
}).done(function() {
alert("댓글 삭제 완료");
location.reload(true);
}).fail(function(error) {
alert(JSON.stringify(error));
});
}
'Web > Spring' 카테고리의 다른 글
스프링 요청 매핑 (1) | 2023.10.29 |
---|---|
로깅 (1) | 2023.10.28 |
[Spring Boot] 게시판 프로젝트 - 04. 회원정보 수정 (0) | 2023.10.01 |
[Spring Boot] 게시판 프로젝트 - 03. 게시판 글 CRUD (0) | 2023.09.30 |
[Spring Boot] 게시판 프로젝트 - 02. 회원가입 및 로그인 (0) | 2023.09.25 |