학습 목표
게시글 삭제 기능을 구현할 수 있다.
BoardRepository.java
게시글 삭제 쿼리를 만들어 보자.
더보기
package com.tenco.blog_v1.board;
import jakarta.persistence.EntityManager;
import jakarta.persistence.Query;
import jakarta.persistence.TypedQuery;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;
import java.util.List;
@Repository // Ioc 대상
@RequiredArgsConstructor
public class BoardRepository {
private final EntityManager em;
/**
* 게시글 조회 메서드
* @param id 조회할 게시글 ID
* @return 조회된 Board 엔티티(Entity), 존재하지 않으면 Null 반환
*/
public Board findById(int id) {
return em.find(Board.class, id);
}
/**
* JPQL의 FETCH 조인 사용 - 성능 최적화
* 한방에 쿼리를 사용해서 즉, 직접 조인해서 데이터를 가져 옵니다.
* @param id
* @return
*/
public Board findByIdJoinUser(int id) {
// JPQL -> Fetch join 을 사용해 보자.
String jpql = " SELECT b FROM Board b JOIN FETCH b.user WHERE b.id = :id ";
return em.createQuery(jpql, Board.class)
.setParameter("id", id)
.getSingleResult();
}
/**
* 모든 게시글 조회
* @return 게시글 리스트
*/
public List<Board> findAll() {
TypedQuery<Board> jpql = em.createQuery("SELECT b FROM Board b ORDER BY b.id DESC", Board.class);
return jpql.getResultList();
}
/**
* em.persist(board) --> 비영속 상태인 엔티티를 영속상태로 전환
* @param board
* @return
*/
@Transactional
public Board save(Board board) {
em.persist(board);
return board;
}
/**
* 게시글 삭제하기
* @param id
*/
// DELETE JPA API 메서드를 활용(영속성 컨텍스트), JPQL --> QDSL .. namedQuery. ...
@Transactional // 트랜잭션 내에서 실행되도록 보장
public void deleteById(int id) {
Query jpql = em.createQuery("DELETE FROM Board b WHERE b.id = :id");
jpql.setParameter("id", id);
jpql.executeUpdate();
}
}
BoardController.java
게시글 삭제 요청을 만들어 보자
더보기
package com.tenco.blog_v1.board;
import com.tenco.blog_v1.user.User;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpSession;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.*;
import java.util.List;
@Slf4j
@RequiredArgsConstructor
@Controller
public class BoardController {
// DI
// @Autowired
// 네이티브 쿼리 연습
private final BoardNativeRepository boardNativeRepository;
// JPA API, JPQL
private final BoardRepository boardRepository;
// 세션을 받기위한 준비
private final HttpSession session;
// 주소설계 - http://localhost:8080/board/10/delete (form 활용하기 때문에 delete 선언)
// form 태그에서는 GET, POST 방식만 지원하기 때문이다.
@PostMapping("/board/{id}/delete")
public String delete(@PathVariable(name = "id") Integer id) {
// 유효성, 인증검사
// 세션에서 로그인 사용자 정보 가져오기 --> 인증(로그인 여부), 인가(권한 -> 내가 작성한 글 여부)
User sessionUser = (User)session.getAttribute("sessionUser");
if(sessionUser == null) {
return "redirect:/login-form";
}
// 권한 체크
Board board = boardRepository.findById(id);
if(board == null) {
return "redirect:/error-404";
}
if( ! board.getUser().getId().equals(sessionUser.getId())) {
return "redirect:/error-403";
}
boardRepository.deleteById(id);
// boardNativeRepository.deleteById(id);
return "redirect:/";
}
// 특정 게시글 요청 확인
// 주소설계 - http://localhost:8080/board/1
@GetMapping("/board/{id}")
public String detail(@PathVariable(name = "id") Integer id, HttpServletRequest request) {
// JPA API 사용
// Board board = boardNativeRepository.findById(id);
// request.setAttribute("board", board);
// JPQL FETCH join 사용
Board board = boardRepository.findByIdJoinUser(id);
request.setAttribute("board", board);
return "board/detail";
}
/**
* http://localhost:8080/
* @param model
* @return
*/
@GetMapping("/")
public String index(Model model) {
//List<Board> boardList = boardNativeRepository.findAll();
List<Board> boardList = boardRepository.findAll();
model.addAttribute("boardList", boardList);
log.warn("여기까지 오나?");
// log.info("boardList : " + boardList);
// templates 폴더 안에 있는 index.mustache 실행
return "index";
}
// 주소설계 - http://localhost:8080/board/save-form
// 게시글 작성 화면
@GetMapping("/board/save-form")
public String saveForm() {
return "board/save-form";
}
// 게시글 저장
// 주소설계 - http://localhost:8080/board/save
@PostMapping("/board/save")
public String save(@ModelAttribute BoardDTO.SaveDTO reqDto) {
User sessionUser = (User)session.getAttribute("sessionUser");
if(sessionUser == null) {
return "redirect:/login-form";
}
// 파라미터가 올바르게 전달 되었는지 확인하기 위해서 사용
log.warn("save 실행: 제목={}, 내용={}", reqDto.getTitle(), reqDto.getContent());
// boardNativeRepository.save(title, content);
// SaveDTO에서 toEntity 메서드를 사용해서 Board 엔티티로 변환하고 인수값으로 User 정보를 넣었다.
// 결국 Board 엔티티로 반환이 된다.
boardRepository.save(reqDto.toEntity(sessionUser));
return "redirect:/";
}
// 게시글 수정 화면 요청
@GetMapping("/board/{id}/update-form")
public String update(@PathVariable(name = "id")Integer id, HttpServletRequest request) {
Board board = boardNativeRepository.findById(id);
request.setAttribute("board", board);
// src/main/resource/templates/board/update-form.mustache
return "board/update-form";
}
// 게시글 수정 요청 기능
// board/{id}/update
@PostMapping("/board/{id}/update")
public String update(@PathVariable(name = "id")Integer id, @RequestParam(name = "title") String title, @RequestParam(name = "content") String content) {
// 업데이트 기능이 완료되면 디테일로 자기자신
boardNativeRepository.updateById(id, title, content);
return "redirect:/board/detail" + id;
}
}



젝
'Spring boot' 카테고리의 다른 글
| 2024.10.10 Blog 프로젝트 만들기(JPA) 회원 가입 기능 만들기 (0) | 2024.10.10 |
|---|---|
| 2024.10.10 Blog 프로젝트 만들기(JPA) 게시글 수정 하기 (0) | 2024.10.10 |
| 2024.10.08 Blog 프로젝트 만들기(JPA) 게시글 쓰기 (0) | 2024.10.08 |
| 2024.10.08 Blog 프로젝트 만들기(JPA) 로그인 & 로그아웃 구현하기 (0) | 2024.10.08 |
| 2024.10.08 Blog 프로젝트 만들기(JPA) 게시글 목록보기 (Post List View) (1) | 2024.10.08 |