
1. View 확인하기
- title, content, username, id(PK-관리를 위해)


2. BoardNativeRepository 에 findById() 만들기
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 BoardNativeRepository {
private final EntityManager em;
public Board findById(int id) {
Query query = em.createNativeQuery("select * from board_tb where id = ?", Board.class);
query.setParameter(1, id);
return (Board) query.getSingleResult();
}
public List<Board> findAll() {
Query query = em.createNativeQuery("select * from board_tb order by id desc", Board.class); // join은 DTO로 받아야
return (List<Board>) query.getResultList(); // 캐스팅 해주기
}
@Transactional
public void save(String title, String content, String username) {
Query query = em.createNativeQuery("insert into board_tb (title, content, username, created_at) values (?,?,?,now())");
query.setParameter(1, title);
query.setParameter(2, content);
query.setParameter(3, username);
query.executeUpdate();
}
}
2-1. findById() 단위 테스트하기
- 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.BoardNativeRepository;
import java.util.List;
@Import(BoardNativeRepository.class)
@DataJpaTest
public class BoardNativeRepositoryTest {
@Autowired // DI
private BoardNativeRepository boardNativeRepository;
@Test
public void findById_test() {
//given - 지금은 넣을게 없음
int id = 1;
//when
Board board = boardNativeRepository.findById(id);
System.out.println("findById_test : " + board);
//then
//org.assertj.core.api
// Assertions.assertThat(boardList.size()).isEqualTo(4);
// Assertions.assertThat(boardList.get(2).getUsername()).isEqualTo("ssar");
}
@Test
public void findAll_test() {
//given - 지금은 넣을게 없음
//when
List<Board> boardList = boardNativeRepository.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");
}
}

- 내용 확인하기
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.BoardNativeRepository;
import java.util.List;
@Import(BoardNativeRepository.class)
@DataJpaTest
public class BoardNativeRepositoryTest {
@Autowired // DI
private BoardNativeRepository boardNativeRepository;
@Test
public void findById_test() {
//given - 지금은 넣을게 없음
int id = 1;
//when
Board board = boardNativeRepository.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 = boardNativeRepository.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");
}
}


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.util.List;
@RequiredArgsConstructor
@Controller
public class BoardController {
private final BoardNativeRepository boardNativeRepository;
@GetMapping("/")
public String index(HttpServletRequest request) {
// 조회하기
List<Board> boardList = boardNativeRepository.findAll();
// 가방에 담기
request.setAttribute("boardList", boardList);
return "index"; // 서버가 내부적으로 index를 요청 - 외부에서는 다이렉트 접근이 안됨
}
@PostMapping("/board/save")
public String save(String title, String content, String username) { // DTO 없이 구현
boardNativeRepository.save(title, content, username);
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 = boardNativeRepository.findById(id);
request.setAttribute("board", board);
return "board/detail";
}
}
4. View에 수정하기
- Post로 요청하기
Get 으로 하는 삭제 요청은 매우 위험함
{{> /layout/header}}
<div class="container p-5">
<!-- 수정삭제버튼 -->
<div class="d-flex justify-content-end">
<!-- Post 요청-> 해당 페이지로 이동-->
<a href="/board/{{board.id}}/update-form" class="btn btn-warning me-1">수정</a>
<!-- Post 요청 -> 해당 페이지 삭제 -->
<form action="/board/{{board.id}}/delete" method="post">
<button class="btn btn-danger">삭제</button>
</form>
</div>
<div class="d-flex justify-content-end">
<b>작성자</b> : {{board.username}}
</div>
<!-- 게시글내용 -->
<div>
<h2><b>{{board.title}}</b></h2>
<hr/>
<div class="m-4 p-2">
{{board.content}}
</div>
</div>
<!-- 댓글 -->
<div class="card mt-3">
<!-- 댓글등록 -->
<div class="card-body">
<form action="/reply/save" method="post">
<textarea class="form-control" rows="2" name="comment"></textarea>
<div class="d-flex justify-content-end">
<button type="submit" class="btn btn-outline-primary mt-1">댓글등록</button>
</div>
</form>
</div>
<!-- 댓글목록 -->
<div class="card-footer">
<b>댓글리스트</b>
</div>
<div class="list-group">
<!-- 댓글아이템 -->
<div class="list-group-item d-flex justify-content-between align-items-center">
<div class="d-flex">
<div class="px-1 me-1 bg-primary text-white rounded">cos</div>
<div>댓글 내용입니다</div>
</div>
<form action="/reply/1/delete" method="post">
<button class="btn">🗑</button>
</form>
</div>
<!-- 댓글아이템 -->
<div class="list-group-item d-flex justify-content-between align-items-center">
<div class="d-flex">
<div class="px-1 me-1 bg-primary text-white rounded">ssar</div>
<div>댓글 내용입니다</div>
</div>
<form action="/reply/1/delete" method="post">
<button class="btn">🗑</button>
</form>
</div>
</div>
</div>
</div>
{{> /layout/footer}}




Share article