11. 게시판 글수정하기v2

송민경's avatar
Mar 13, 2024
11. 게시판 글수정하기v2

1. update 사용하기

  • 조회해서 영속화시킨 다음 영속화된 객체를 변경
  • 트랜잭션 종료 시 update 쿼리를 전송해서 변경함
 
결과 값이 없을 때
  • delete는 파싱할게 없음 → 오류 없음
비정상적인 접근은 서비스에서 로그는 남겨서 IP를 BL에 등록함
  • select는 받은 결과를 파싱해야 함 → 오류 남
  • update는 파싱할게 없음 → 오류 없음
update board_tb set content='내용수정' where id = 1; SELECT * FROM BOARD_TB; SELECT * FROM BOARD_TB where id =5; update board_tb set content='내용수정' where id = 5;
notion image

2. 단위 테스트하기

package shop.mtcoding.blog.Board; import jakarta.persistence.EntityManager; 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 static org.assertj.core.api.AssertionsForClassTypes.assertThat; @Import(BoardPersistRepository.class) @DataJpaTest public class BoardPersistRepositoryTest { @Autowired //DI private BoardPersistRepository boardPersistRepository; @Autowired private EntityManager em; @Test public void updateById_test(){ //given int id = 1; String title = "제목수정1"; //when Board board = boardPersistRepository.findById(id); System.out.println("updateById_test findById : " + board); board.setTitle(title); // PC에 있는 값을 변경 //then em.flush(); System.out.println("updateById_test updateById : " + board); } // @Test // public void deleteByIdv2_test(){ // // given // int id = 1; // // // when // boardPersistRepository.deleteByIdv2(id); // // em.flush(); // 버퍼에 쥐고 있는 쿼리를 즉시 전송 // } @Test public void deleteById_test(){ // given int id = 5; // when Board board = boardPersistRepository.findById(id); em.clear(); // PC를 다 비우는 것 boardPersistRepository.deleteById(id); // then List<Board> boardList = boardPersistRepository.findAll(); System.out.println("deleteById_test/size : " + boardList.size()); } @Test public void findById_test() { //given int id = 1; //when Board board = boardPersistRepository.findById(id); boardPersistRepository.findById(id); System.out.println("findById_test : " + board); } @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); } }
notion image
 

3. Board 에 update() 만들기

  • 변경할 데이터를 설정할 setter 만들기
  • 다른 곳에서 재사용하려면 DTO이름을 적어둘 수 없음
package shop.mtcoding.blog.board; import jakarta.persistence.*; import lombok.Data; import lombok.NoArgsConstructor; import org.hibernate.annotations.CreationTimestamp; import shop.mtcoding.blog.util.MyDateUtil; import java.sql.Timestamp; @NoArgsConstructor // 빈생성자 만들어주기 @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; @CreationTimestamp // PC로 인해 DB에 INSERT될 때 날짜 주입 private Timestamp createdAt; public Board(String title, String content, String username) { this.title = title; this.content = content; this.username = username; } // 다른 곳에서 재사용하려면 DTO이름을 적어둘 수 없음 public void update(BoardRequest.UpdateDTO reqDTO) { // 변경할 데이터를 설정할 setter 만들기 this.title = reqDTO.getTitle(); this.content = reqDTO.getContent(); this.username = reqDTO.getUsername(); } public String getBoardDate(){ return MyDateUtil.timestampFormat(createdAt); } }
 

4. BoardRequest 에 UpdateDTO 만들기

package shop.mtcoding.blog.board; import lombok.Data; public class BoardRequest { @Data public static class SaveDTO { private String title; private String content; private String username; // Entity로 바꾸는 메서드 - 비영속 객체를 PC에 넣기 위해 insert 때만 필요함 public Board toEntity(){ return new Board(title, content, username); } } @Data public static class UpdateDTO { private String title; private String content; private String username; } }
 

5. BoardPersistRepository 에 updateById() 만들기

  • 더티체킹 : 영속화된 객체의 상태를 변경하고 트랜잭션이 종료되면 update가 됨
  • 원래는 안만들어도 되나 트랜잭션을 걸어주기 위해 만듦
  • 안만들거면 controller에 트랜잭션을 걸어도 되지만 그럼 시간이 길어짐
  • 후에 service 레이어를 만들어 수정해야 함
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; @Transactional public void updateById(int id,BoardRequest.UpdateDTO reqDTO) { Board board = findById(id); // 영속화됨 board.update(reqDTO); }// 더티체킹 // @Transactional // public void deleteByIdv2(Integer id) { // Board board = findById(id); // em.remove(board); // PC에 객체를 지우고, (트랜잭션 종료 시) 삭제 쿼리를 전송함 // } @Transactional public void deleteById(Integer id) { Query query = em.createQuery("delete from Board b where b.id = :id"); query.setParameter("id", id); query.executeUpdate(); } 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; } }
 

6. BoardController 에 update 수정하기

package shop.mtcoding.blog.board; import ch.qos.logback.core.model.Model; import jakarta.servlet.http.HttpServletRequest; import jakarta.transaction.Transactional; 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; // @Transactional 트랜잭션 시간이 너무 길어져서 service에 넣어야함 @PostMapping("/board/{id}/update") public String update(@PathVariable Integer id, BoardRequest.UpdateDTO reqDTO) { boardPersistRepository.updateById(id, reqDTO); return "redirect:/board/" + id; } @GetMapping("/board/{id}/update-form") public String updateForm(@PathVariable(name = "id") Integer id, HttpServletRequest request) { Board board = boardPersistRepository.findById(id); request.setAttribute("board", board); return "/board/update-form"; // 서버가 내부적으로 index를 요청 - 외부에서는 다이렉트 접근이 안됨 } @PostMapping("/board/{id}/delete") public String delete(@PathVariable Integer id) { // DTO 없이 구현 boardPersistRepository.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"; } }
notion image
 
Share article

vosw1