update(PUT)와 delete(DELETE)는 JS를 사용해야 하는데 지금은 JS를 배우기 전이라 내 실력으로는 할 수 없다.
하지만 Http 1.1부터 POST가 Http 4가지 메서드를 모두 지원했기 때문에
@PostMapping("/boards/{id}/delete")
@PostMapping("/boards/{id}/update")
주소를 이렇게 설정해 Post요청으로 update와 delete를 시도해 볼 수 있다. 임시로 주소를 이렇게 정했지만, 원래는 주소에 동사가 들어가면 안된다.
<delete id="delete">
DELETE FROM boards WHERE id = #{id}
</delete>
@PostMapping("/boards/{id}/delete")
public String deleteBoards(@PathVariable Integer id) {
boardsDao.delete(id);
return "redirect:/";
}
그런데 우리는 POSTMAN으로 POST요청을 하여 delete를 한다. 이 경우 id가 없는 번호로 삭제가 요청될 수 있다...!
✔️ 영속화하여 delete 하기
id가 없는 경우 delete를 실행하면 오류가 나지 않고 0행이 수정되었다는 결과가 나온다. (결과값 0)
문제는 delete를 해본 뒤 결과값을 보고 다시 처리하는 방법이 좋지 않다는 점이다.
일단 영속화(select)를 해서 delete를 하는 것이 좋다.💡 영속화가 유리한 이유 : 트랜잭션
DB에서 가장 데이터 부하가 심할 때는 트랜잭션이 일어날 때다.
데이터를 READ할 때는 누구나 접근 가능하나, 트랜잭션을 할 때에는 데이터의 동기화를 위해 다른 사용자가 트랜잭션을 실행하지 못하게 막기 때문이다.
👉 따라서 트랜잭션이 일어나지 않게 두 번의 연산(select, delete)이 일어나도 영속화를 한 뒤 delete를 하는 것이 낫다.
@PostMapping("/boards/{id}/delete")
public String deleteBoards(@PathVariable Integer id) {
//영속화
Boards boardsPS = boardsDao.findById(id);
if(boardsPS == null) { // if는 비정상 로직을 타겟 해서 걸러내는 필터 역할을 하는 게 좋음
return "redirect:/boards/"+id;
}
boardsDao.delete(id);
return "redirect:/";
}
return "redirect:/boards/"+id;
으로 적어줘야 한다.영속화를 하여 행을 모두 불러온 뒤 지워야 하므로 mapper도 수정
<select id="findById"
resultType="site.metacoding.red.domain.boards.Boards">
SELECT id, title, content, usersId, createdAt
FROM boards
WHERE id = #{id}
</select>
@PostMapping("/boards/{id}/delete")
public String deleteBoards(@PathVariable Integer id) {
Users principal = (Users) session.getAttribute("principal");
// 영속화 : 하나의 코드로 떼어서 사용하기 위해 principal 뒤에 적었음 (boardsPS와 if문 묶음)
Boards boardsPS = boardsDao.findById(id);
if (boardsPS == null) { // if는 비정상 로직을 타겟 해서 걸러내는 필터 역할을 하는 게 좋음
return "redirect:/boards/" + id;
}
// 인증 체크
if (principal == null) {
return "redirect:/loginForm";
}
}
principal의 Id()
와boardsPS의 userId
를 비교
@PostMapping("/boards/{id}/delete")
public String deleteBoards(@PathVariable Integer id) {
Users principal = (Users) session.getAttribute("principal");
// 영속화 : 하나의 코드로 떼어서 사용하기 위해 principal 뒤에 적었음 (boardsPS와 if문 묶음)
Boards boardsPS = boardsDao.findById(id);
if (boardsPS == null) { // if는 비정상 로직을 타겟 해서 걸러내는 필터 역할을 하는 게 좋음
return "redirect:/boards/" + id;
}
// 인증 체크
if (principal == null) {
return "redirect:/loginForm";
}
// 권한 체크 ( 세션 principal.getId() 와 boardsPS의 userId를 비교)
if (principal.getId() != boardsPS.getUsersId()) {
return "redirect:/boards/" + id;
}
boardsDao.delete(id);
return "redirect:/";
}
<form>
<button class="btn btn-warning">수정하러가기</button>
</form>
<form>
<button class="btn btn-danger">삭제</button>
</form>
버튼을 가로로 배치하고 싶다.
🔥 이 때 form태그에 두 개의 button을 넣는 건 안 된다. 서로 다른 action을(update, delete) 가질 예정이기 때문이다.
<div class="d-flex">
<form>
<button class="btn btn-warning">수정하러가기</button>
</form>
<form>
<button class="btn btn-danger">삭제</button>
</form>
</div>
<form action="/boards/${boards.id}/delete" method="post">
<button class="btn btn-danger">삭제</button>
</form>
${boards.id}
로 id 설정 가능 <c:if test="${principal.id == boards.usersId}">
<div class="d-flex">
<form>
<button class="btn btn-warning">수정하러가기</button>
</form>
<form action="/boards/${boards.id}/detail" method="post">
<button class="btn btn-danger">삭제</button>
</form>
</div>
</c:if>