게시글 상세보기 페이지 만들기
[index.jsp] 메인페이지
<div class="container">
<c:forEach var="board" items="${boards.content}">
<div class="card m-2">
<div class="card-body">
<h4 class="card-title">${board.title}</h4>
<a href="/board/${board.id}" class="btn btn-primary">상세보기</a>
</div>
</div>
</c:forEach>
...
id를 이용해 글 상세보기 페이지로 이동
1. id로 찾는 글상세보기 get매핑 만들기
[BoardController]
@GetMapping("/board/{id}")
public String findById(@PathVariable int id, Model model) {
model.addAttribute("board",boardService.글상세보기(id));
return "board/detail";
}
model을 이용해 데이터(id)를 가지고 뷰페이지(board/detail)로 가져간다.
2. 글상세보기(id) 메서드 생성하기
public Board 글상세보기(int id) {
return boardRepository.findById(id)
.orElseThrow(()->{
return new IllegalArgumentException("글 상세보기 실패 : 아이디를 찾을 수 없습니다.");
});
}
3. return "board/detail"; 뷰페이지 만들기
[detail.jsp]
<!-- 글 상세보기 페이지 -->
<div class="container">
<button class="btn btn-secondary" onclick="history.back()">돌아가기</button>
<c:if test="${board.user.id == principal.user.id }">
<button id="btn-update" class="btn btn-warning">수정</button>
<button id="btn-delete" class="btn btn-danger">삭제</button>
</c:if>
<br><br>
<div class="form-group">
<h3>${board.title}</h3>
</div>
<hr>
<div>
<div>${board.content}</div>
</div>
<hr>
</div>
<script src="/js/board.js"></script>
<%@ include file="../layout/footer.jsp"%>
-결과화면
본인만 수정, 삭제하도록 하려면?
게시글을 쓴 유저아이디와 가입한 유저의 아이디가 같아야함
<c:if test="${board.user.id == principal.user.id }">
<button id="btn-update" class="btn btn-warning">수정</button>
<button id="btn-delete" class="btn btn-danger">삭제</button>
</c:if>
다른 유저면 수정,삭제버튼 안보이도록
** principal은 PrincipalDetail 클래스를 말한다. (User객체의 id)
@Getter
public class PrincipalDetail implements UserDetails{
private User user; // 콤포지션( 객체를 들고 있는)
...
게시글 삭제하기
삭제버튼 클릭 시 게시글이 삭제는 자바스크립트로 동작실행한다.
- <button id="btn-delete" class="btn btn-danger">삭제</button>
1. 게시글을 삭제할때는 해당 페이지에 id가 필요하다. (뷰페이지에 id 와 작성자를 추가)
[detail.jsp]
<div>
글 번호 : <span id="id"><i>${board.id} </i></span>
작성자 : <span><i>${board.user.username} </i></span>
</div>
2. 삭제 버튼 누르면 자바스크립트 ajax 실행
[board.js]
// 글 상세보기 삭제
let index = {
init: function(){
$("#btn-delete").on("click", ()=>{
this.deleteById();
});
},
deleteById: function() {
let id = $("#id").text();
$.ajax({
//글삭제 수행 요청
type:"DELETE",
url:"/api/board/" + id,
dataType: "json"
}).done(function(resp){
alert("삭제가 완료되었습니다.");
location.href="/";
}).fail(function(error){
alert(JSON.stringify(error));
});
},
삭제버튼을 눌렀을때 함수실행
deleteById: function() {
let id = $("#id").text();
#id 의 text값 ▶ 글 번호 : <span id="id"><i>${board.id} </i></span>
text값인 <i>${board.id} </i>을 가져와야한다.
※주의
.val()값이 아님!!
.val() 과 .text() 차이점
- update 경우 let id = $("#id").val() 를 쓴 이유는
#id 의 value값이라서 .val()
<input type="hidden" id="id" value="${board.id}"/>
- delete 는 let id = $("#id").text() 를 썼다
사이값이 html이라서 .text()
<span id="id"><i>${board.id} </i></span>
이제 url:"/api/board/" + id 주소의 Controller 만들기 (삭제할때 id 의 값을 url에 넣는다.)
3. 주소값이 "/api/board/" + id 값인 [BoardApiController] 로 이동
@DeleteMapping("/api/board/{id}")
public ResponseDto<Integer> deleteById(@PathVariable int id){
boardService.글삭제하기(id);
return new ResponseDto<Integer>(HttpStatus.OK.value(), 1);
}
4. 글삭제하기 메서드 만들기
[BoardService]
@Transactional
public void 글삭제하기(int id) {
boardRepository.deleteById(id);
}
** @Transactional 어노테이션 모두 붙여주는데
select만 하는 글목록()과 글상세보기() 메서드는 @Transactional(readOnly = true) 붙여주기
게시글 수정 페이지
수정하기 버튼을 button태그말고 a태그로 해서 하이퍼링크로 연결하기
- <a href="/board/${board.id}/updateForm" class="btn btn-warning">수정</button>
1. [BoardController]
@GetMapping("/board/{id}/updateForm")
public String updateForm(@PathVariable int id, Model model) {
model.addAttribute("board",boardService.글상세보기(id));
return "board/updateForm";
}
model을 이용해 뷰페이지에 데이터를 가져올 수 있다.
어떻게? 글상세보기()데이터를 가져와 "board" 키 값에 담아 제목은 ${board.title} 내용은 ${board.content}
2. return "board/updateForm"; 뷰페이지 만들기
( saveForm 복사해서 만들기)
[updateForm] 게시글 수정 페이지
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<!-- /layput/header.jsp 하면 페이지 못찾음 -->
<%@ include file="../layout/header.jsp"%>
<div class="container">
<form>
<input type="hidden" id="id" value="${board.id}"/> //id 추가
<div class="form-group">
<input value="${board.title}" type="text" class="form-control" placeholder="Enter title" id="title">
</div>
<div class="form-group">
<textarea class="form-control summernote" rows="5" id="content">${board.content}</textarea>
</div>
</form>
<button id="btn-update" class="btn btn-primary">글 수정완료</button>
</div>
<script>
$('.summernote').summernote({
tabsize: 2,
height: 300
});
</script>
<script src="/js/board.js"></script>
<%@ include file="../layout/footer.jsp"%>
☆ 수정할때는 제목과 내용만으로 수정을 할 수가 없어서 hidden값으로 board.id를 추가한다.
+추가 <input type="hidden" id="id" value="${board.id}"/>
이제 수정완료 버튼을 클릭시 자바스크립트 ajax로 요청한다
- <button id="btn-update" class="btn btn-primary">글 수정완료</button>
3. [board.js]
let index = {
init: function() {
$("#btn-update").on("click", () => {
this.update();
});
},
//글 수정하기(update)
update: function() {
let id = $("#id").val(); // 추가한 <input type="hidden" id="id" value="${board.id}"/>
let data = {
title: $("#title").val(),
content: $("#content").val(),
}
$.ajax({
//글 수정하기 수행 요청
type:"PUT", //수정은 put
url:"/api/board/" + id,
data:JSON.stringify(data),
contentType:"application/json; charset=utf-8",
dataType: "json"
}).done(function(resp){
alert("글 수정이 완료되었습니다.");
location.href="/";
}).fail(function(error){
alert(JSON.stringify(error));
});
},
}
id, data를 가지고 url:"/api/board/" + id 주소인 Controller 로 이동
4. [BoardApiController]
@PutMapping("/api/board/{id}")
public ResponseDto<Integer> update(@PathVariable int id, @RequestBody Board board){
BoardService.글수정하기(id,board);
return new ResponseDto<Integer>(HttpStatus.OK.value(),1);
}
5. [BoardService] 글 수정하기() 메서드 만들기
@Transactional
public void 글수정하기(int id, Board requestBody) {
Board board = boardRepository.findById(id)
.orElseThrow(()->{
return new IllegalArgumentException("글 찾기 실패 : 아이디를 찾을 수 없습니다.");
}); //영속화 완료
board.setTitle(requestBody.getTitle());
board.setContent(requestBody.getContent());
// 해당 함수 종료시 (Service가 종료될때) 트랜잭션이 종료됩니다. 이때 더티체킹 - 자동 업데이트가 된다.
}
@Transactional 어노테이션의 역할
5-1) findById(id) 해서 영속성 컨텍스트에 board가 들어옴(영속화)
5-2) 서버에 있는 board 값을 변경하고
board.setTitle(requestBody.getTitle());
board.setContent(requestBody.getContent());
5-3)
글수정하기() 메서드가 종료하면 Service가 종료가 되고 동시에 트랜잭션도 종료가 된다.
트랜잭션이 종료가 되면 변경감지 후 수정된 값이 DB에 자동으로 넣어진다(flush)
이 과정을 '더티 체킹' 이라고 한다.
* @Transactional 어노테이션을 붙여야 트랜잭션 작동하고 '상태 변경 검사' 를 한다
영속화란?
board객체를 save를 했을때
: jpa 영속성 컨텍스트 공간 안에 1차 캐쉬로 '영속화' 된 board 객체가 생성된다. → 영속화 된 board 객체를 DB에 넣는다.
update를 했을때
: DB의 2번 board 객체 데이터를 영속성 컨텍스트에 들고와서 1차캐시에 넣음 = 2번 board 객체가 영속화 되었다.
'Spring boot | 블로그 만들기' 카테고리의 다른 글
블로그 만들기 | 회원 정보 수정하기2 - Authentication객체 만들어 세션값 변경 (0) | 2022.11.17 |
---|---|
블로그 만들기 | 회원 정보 수정하기 1 (0) | 2022.11.15 |
블로그 만들기 | 게시글 목록 보기, 페이징 처리하기 (0) | 2022.11.14 |
블로그 만들기 | 게시글 쓰기 (0) | 2022.11.14 |
스프링 시큐리티 로그인 | loadUserByUsername 오버라이드, 암호화 된 비밀번호 비교하기 (0) | 2022.11.13 |