
1. find로 한 건 조회하기
- 캐싱을 사용하여 데이터베이스 쿼리를 최적화하는 것
 
- 요청에 대한 응답을 캐시
 
      후에 동일한 요청이 발생할 때 다시 데이터베이스에 액세스하지 않고 캐시된 결과를 반환

- 1번의 PK를 가진 보드 객체를 조회
 
       - 있을 경우
          이 경우 캐싱을 사용하여 해당 객체를 메모리에 저장
          이후에 다시 동일한 PK를 가진 객체를 요청할 때는 바로 캐시된 객체를 반환
       - 없을 경우
          캐시에서 요청된 객체를 찾지 못한 경우에 대한 실패를 캐시 시스템이 확인
          데이터베이스에 대한 조회 쿼리가 생성 / 캐싱된 객체를 찾을 수 없는 경우에만 실
          요청된 PK를 기반으로 데이터베이스의 특정 테이블에서 객체를 검색하는 SELECT 쿼리
          데이터베이스에서 객체를 검색한 후에는 검색된 객체를 메모리에 로드하여 응답을 생성
          조회된 객체는 캐시에 저장하기 전에 즉시반환
          객체가 캐시에 저장되어야 할 경우, 데이터베이스로부터 가져온 객체가 캐시에 저장
          이후 동일한 요청이 발생할 때는 캐시된 객체 사용 가능
         조회된 객체를 클라이언트에게 응답으로 전달
- 주의할 점 : 항상 최신 상태인지 확인, 데이터가 변경될 때 적절하게 캐시를 갱신이 필요
 
- 요청이 올 때 객체 생성과 초기화
 
      요청이 오면 새로운 보드 객체를 생성
      일반적으로 기본 생성자를 호출하여 객체를 생성
      새로 생성된 보드 객체는 초기화 단계를 거침 / 필요한 속성들을 설정하고 객체를 준비하는 단계
- 응답을 받은 경우 객체의 상태 변화:
 
이 응답에 포함된 보드 객체를 영속화 : 객체를 메모리에 저장하고 캐시에 넣어둠
      이후 동일한 요청이 오면 캐시에서 해당 객체를 찾을 수 있음
      다시 객체를 생성할 필요 없이 캐시된 객체를 사용하여 응답을 바로 반환
2. BoardPersistRepository 에 findById() 만들기
- 한 건을 찾을 땐 find 사용하기
 
package shop.mtcoding.blog.board;
import jakarta.persistence.EntityManager;
import jakarta.persistence.Query;
import jakarta.transaction.Transactional;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Repository;
import java.util.List;
@RequiredArgsConstructor
@Repository
public class BoardPersistRepository {
    private final EntityManager em;
    public Board findById(Integer id) {
        Board board = em.find(Board.class, id); // (class명, PK)
        return board;
    }
    public List<Board> findAll() {
        Query query = em.createQuery("select b from Board b order by b.id desc", Board.class);
        return query.getResultList();
    }
    @Transactional
    public Board save(Board board) {
        // PC에 Data 주소 넣기(Entity만 가능함)
        em.persist(board);
        // 실행후 영속 객체가 됨
        return board;
    }
}
- 단위 테스트 하기
 
package shop.mtcoding.blog.Board;
import org.assertj.core.api.Assertions;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest;
import org.springframework.context.annotation.Import;
import shop.mtcoding.blog.board.Board;
import shop.mtcoding.blog.board.BoardPersistRepository;
import java.util.List;
@Import(BoardPersistRepository.class)
@DataJpaTest
public class BoardPersistRepositoryTest {
    @Autowired //DI
    private BoardPersistRepository boardPersistRepository;
    @Test
    public void findById_test() {
        //given 
        int id = 1;
        //when
        Board board = boardPersistRepository.findById(id);
        System.out.println("findById_test : " + board);
        //then
        //org.assertj.core.api
        Assertions.assertThat(board.getTitle()).isEqualTo("제목1");
        Assertions.assertThat(board.getContent()).isEqualTo("내용1");
    }
    @Test
    public void findAll_test() {
        //given - 지금은 넣을게 없음
        //when
        List<Board> boardList = boardPersistRepository.findAll();
        //then
        System.out.println("findAll_test/size : " + boardList.size());
        System.out.println("findAll_test/username : " + boardList.get(2).getUsername());
        //org.assertj.core.api
        Assertions.assertThat(boardList.size()).isEqualTo(4);
        Assertions.assertThat(boardList.get(2).getUsername()).isEqualTo("ssar");
    }
    @Test
    public void save_test() {
        //given
        Board board = new Board("제목5","내용5","ssar");
        //when
        boardPersistRepository.save(board);
        //then
        System.out.println(board);
    }
}
- 1개의 id 두 번 전송 → 1개만 적용
 
@Test
    public void findById_test() {
        //given
        int id = 1;
        //when
        Board board = boardPersistRepository.findById(id);
        boardPersistRepository.findById(id);
        System.out.println("findById_test : " + board);
    }
- 두 개의 id가 다른 경우 → 다 실행
 
 @Test
    public void findById_test() {
        //given
        int id1 = 1;
        int id2 = 2;
        //when
        Board board1 = boardPersistRepository.findById(id1);
        Board board2 = boardPersistRepository.findById(id2);
        System.out.println("findById_test : " + board1);
        System.out.println("findById_test : " + board2);
        }
3. BoardController 에 detail 수정하
package shop.mtcoding.blog.board;
import ch.qos.logback.core.model.Model;
import jakarta.servlet.http.HttpServletRequest;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import java.lang.annotation.Native;
import java.util.List;
@RequiredArgsConstructor
@Controller
public class BoardController {
    private final BoardNativeRepository boardNativeRepository;
    private final BoardPersistRepository boardPersistRepository;
    @PostMapping("/board/{id}/update")
    public String update(@PathVariable Integer id, String title, String content, String username){
        boardNativeRepository.updateById(id, title, content, username);
        return "redirect:/board/"+id;
    }
    @GetMapping("/board/{id}/update-form")
    public String updateForm(@PathVariable (name="id") Integer id, HttpServletRequest request) {
        Board board = boardNativeRepository.findById(id);
        request.setAttribute("board", board);
        return "/board/update-form"; // 서버가 내부적으로 index를 요청 - 외부에서는 다이렉트 접근이 안됨
    }
    @PostMapping("/board/{id}/delete")
    public String delete(@PathVariable Integer id) { // DTO 없이 구현
        boardNativeRepository.deleteById(id);
        return "redirect:/";
    }
    @GetMapping("/")
    public String index(HttpServletRequest request) {
        // 조회하기
        List<Board> boardList = boardPersistRepository.findAll();
        // 가방에 담기
        request.setAttribute("boardList", boardList);
        return "index"; // 서버가 내부적으로 index를 요청 - 외부에서는 다이렉트 접근이 안됨
    }
    @PostMapping("/board/save")
    public String save(BoardRequest.SaveDTO reqDTO) { // DTO 없이 구현
        boardPersistRepository.save(reqDTO.toEntity());
        return "redirect:/";
    }
    @GetMapping("/board/save-form")
    public String saveForm() {
        return "board/save-form";
    }
    @GetMapping("/board/{id}")
    public String detail(@PathVariable Integer id, HttpServletRequest request) { // Integer : 없으면 null, int : 0
        Board board = boardPersistRepository.findById(id);
        request.setAttribute("board", board);
        return "board/detail";
    }
}

Share article