1. 화면보기
2. BoardController 에 index()
- Model 객체의 데이터를 model에 담음
내부에 Request가 담겨있음
- request에 담으면 알아서 버려지니까 용량 관리를 안해도 됨
- session에 담으면 안 버려져서 용량 관리를 해야 함
오래 기록 가능 - 여러 번 이동 후 불러올 때
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; @RequiredArgsConstructor @Controller public class BoardController { private final BoardNativeRepository boardNativeRepository; @GetMapping("/") public String index(HttpServletRequest request) { return "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) { // Integer : 없으면 null, int : 0 return "board/detail"; } }
3. BoardNativeRepository에 findAll() 만들기
3-1. 목록에 뿌려질 데이터 조회하기
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 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(); } }
3-2. 단위 테스트 하기
- 검색해서 찾기
ctrl + R
- 크기 확인하기
package shop.mtcoding.blog.Board; 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 findAll_test(){ //given - 지금은 넣을게 없음 //when List<Board> boardList = boardNativeRepository.findAll(); //then System.out.println("findAll_test/size : " + boardList.size()); } }
- 크기와 사용자 확인하기
package shop.mtcoding.blog.Board; 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 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()); } }
3-3. Assertions 사용하기
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 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"); } }
- 오류가 없으면 결과 값만 출력
- 오류가 나면 알려줌
4. BoardController index()에 추가하기
- 서버가 내부적으로 index를 요청
외부에서는 다이렉트 접근이 안됨
- 요청이 내부적으로 2번 일어나지만 데이터가 들어있는 request는 1개임
내부적으로 request dispatch(내부 데이터 유지)가 일어남
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) { // Integer : 없으면 null, int : 0 return "board/detail"; } }
5. 화면에 뿌리기
5-1. 정보 가져오기
- 화면에 보이는 정보만 가지고 와야 함
Board가 아니라 BoardDTO를 줘야 함
새로운 클래스를 만들어서 옮겨담는 것 / 객체 복사
{{> /layout/header}} <div class="container p-5"> {{#boardList}} <!--for문 돌리기--> <div class="card mb-3"> <div class="card-body"> <h4 class="card-title mb-3">{{title}}</h4> <a href="/board/{{id}}" class="btn btn-primary">상세보기</a> </div> </div> {{/boardList}} <ul class="pagination d-flex justify-content-center"> <li class="page-item disabled"><a class="page-link" href="#">Previous</a></li> <li class="page-item"><a class="page-link" href="#">Next</a></li> </ul> </div> {{> /layout/footer}}
5-2. 날짜, 시간 추가하기
{{> /layout/header}} <div class="container p-5"> {{#boardList}} <!--for문 돌리기--> <div class="card mb-3"> <div class="card-body"> <h4 class="card-title mb-3">{{title}}</h4> <div class="mb-3">{{createdAt}}</div> <!--날짜 시간 추가하기--> <a href="/board/{{id}}" class="btn btn-primary">상세보기</a> </div> </div> {{/boardList}} <ul class="pagination d-flex justify-content-center"> <li class="page-item disabled"><a class="page-link" href="#">Previous</a></li> <li class="page-item"><a class="page-link" href="#">Next</a></li> </ul> </div> {{> /layout/footer}}
5-3. 날짜, 시간 커스터마이징하기
- 라이브러리 추가하기
implementation group: 'org.apache.commons', name: 'commons-lang3', version: '3.0'
- 메서드 찾아서 테스트하기
package shop.mtcoding.blog.util; import org.apache.commons.lang3.time.DateFormatUtils; import org.junit.jupiter.api.Test; import java.sql.Timestamp; import java.util.Date; public class DateTest { @Test public void format_test(){ Timestamp currentTimestamp = new Timestamp(System.currentTimeMillis()); // Timestamp를 Date 객체로 변환 Date currentDate = new Date(currentTimestamp.getTime()); // 원하는 포맷으로 날짜를 변환 String formattedDate = DateFormatUtils.format(currentDate, "yyyy-MM-dd HH:mm"); // 포맷된 날짜 출력 System.out.println("Formatted Date: " + formattedDate); } }
- 테스트 된 코드 재사용 가능하게 만들기
package shop.mtcoding.blog.util; import org.apache.commons.lang3.time.DateFormatUtils; import java.sql.Timestamp; import java.util.Date; public class MyDateUtil { public static String timestampFormat(Timestamp boardDate){ // 재사용 가능함 Date currentDate = new Date(boardDate.getTime()); return DateFormatUtils.format(currentDate, "yyyy-MM-dd HH:mm"); } }
- 단위 테스트하기
package shop.mtcoding.blog.util; import org.apache.commons.lang3.time.DateFormatUtils; import org.junit.jupiter.api.Test; import java.sql.Timestamp; import java.util.Date; public class DateTest { @Test public void timestampFormat(){ //given Timestamp currentTimestamp = new Timestamp(System.currentTimeMillis()); //when String createdAt = MyDateUtil.timestampFormat(currentTimestamp); //then System.out.println("timestampFormat_test: " + createdAt); } @Test public void format_test(){ Timestamp currentTimestamp = new Timestamp(System.currentTimeMillis()); // Timestamp를 Date 객체로 변환 Date currentDate = new Date(currentTimestamp.getTime()); // 원하는 포맷으로 날짜를 변환 String formattedDate = DateFormatUtils.format(currentDate, "yyyy-MM-dd HH:mm"); // 포맷된 날짜 출력 System.out.println("Formatted Date: " + formattedDate); } }
5-4. Board 테이블에 getBoardDate() 추가하기
- 원래는 DTO에 넣어야 함
package shop.mtcoding.blog.board; import jakarta.persistence.*; import lombok.Data; import shop.mtcoding.blog.util.MyDateUtil; import java.sql.Timestamp; @Data // 변경되는 데이터에만 setter가 필요함 @Table(name = "board_tb") @Entity public class Board { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Integer id; private String title; private String content; private String username; private Timestamp createdAt; public String getBoardDate(){ return MyDateUtil.timestampFormat(createdAt); } }
- view에 boardDate 로 변경하기
{{> /layout/header}} <div class="container p-5"> {{#boardList}} <!--for문 돌리기--> <div class="card mb-3"> <div class="card-body"> <h4 class="card-title mb-3">{{title}}</h4> <div class="mb-3">{{boardDate}}</div> <!--날짜 시간 추가하기--> <a href="/board/{{id}}" class="btn btn-primary">상세보기</a> </div> </div> {{/boardList}} <ul class="pagination d-flex justify-content-center"> <li class="page-item disabled"><a class="page-link" href="#">Previous</a></li> <li class="page-item"><a class="page-link" href="#">Next</a></li> </ul> </div> {{> /layout/footer}}
Share article