19. 게시판 글수정하기v3

송민경's avatar
Mar 15, 2024
19. 게시판 글수정하기v3

1. BoardRepository 에 updateById() 만들기

package shop.mtcoding.blog.board; import jakarta.persistence.EntityManager; import jakarta.persistence.Query; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Repository; import org.springframework.transaction.annotation.Transactional; import shop.mtcoding.blog.user.User; import java.util.HashSet; import java.util.List; import java.util.Set; @RequiredArgsConstructor @Repository public class BoardRepository { private final EntityManager em; // update board_tb set title =? where id=? // update board_tb set content =? where id=? // update board_tb set title =?, content =? where id=? @Transactional public void updateById(int id, String title, String content) { // DTO를 안만들고 꺼내서 넘겨도 됨 -> 재사용 가능 Board board = findById(id); board.setTitle(title); board.setContent(content); } // 더티체킹 @Transactional public void deleteById(int id) { Query query = em.createQuery("delete from Board b where b.id = :id"); query.setParameter("id", id); query.executeUpdate(); } @Transactional public void save(Board board) { em.persist(board); } public List<Board> findAllV3() { String q1 = "select b from Board b order by b.id desc"; List<Board> boardList = em.createQuery(q1, Board.class).getResultList(); int[] userIds = boardList.stream().mapToInt(board -> board.getUser().getId()).distinct().toArray(); String q2 = "select u from User u where u.id in ("; for (int i = 0; i < userIds.length; i++) { if (i == userIds.length - 1) { q2 = q2 + userIds[i] + ")"; } else { q2 = q2 + userIds[i] + ","; } } List<User> userList = em.createQuery(q2, User.class).getResultList(); for (Board board : boardList) { for (User user : userList) { if (user.getId() == board.getUser().getId()) { board.setUser(user); } } } return boardList; // user가 채워져 있어야함. } public List<Board> findAllV2() { Query q1 = em.createQuery("select b from Board b order by b.id desc", Board.class); List<Board> boardList = q1.getResultList(); Set<Integer> userIds = new HashSet<>(); for (Board board : boardList) { userIds.add(board.getUser().getId()); } Query q2 = em.createQuery("select u from User u where u.id in :userIds", User.class); q2.setParameter("userIds", userIds); List<User> userList = q2.getResultList(); for (Board board : boardList) { for (User user : userList) { if (user.getId() == board.getUser().getId()) { board.setUser(user); } } } return boardList; } public List<Board> findAll() { // 다른 정보가 추가로 필요하면 조인하면 됨 - outer join일 때 outer는 생략 가능 Query query = em.createQuery("select b from Board b order by b.id desc", Board.class); return query.getResultList(); } public Board findByIdJoinUser(int id) { // on생략 가능, 알아서 pk연결해줌 Query query = em.createQuery("select b from Board b join fetch b.user u where b.id = :id", Board.class); query.setParameter("id", id); return (Board) query.getSingleResult(); } public Board findById(int id) { //id, title, content, user_id(이질감), created_at Board board = em.find(Board.class, id); return board; } }
 
  • 단위 테스트하기
package shop.mtcoding.blog.Board; import jakarta.persistence.EntityManager; 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.BoardRepository; import shop.mtcoding.blog.user.User; import java.util.List; @Import(BoardRepository.class) @DataJpaTest public class BoardRepositoryTest { @Autowired private BoardRepository boardRepository; @Autowired private EntityManager em; @Test public void updateById_test(){ // given int id = 1; String title = "수정제목1"; String content = "수정내용1"; // when boardRepository.updateById(id, title, content); // delete 쿼리 발동 em.flush(); // then System.out.println("updateById_test : " + boardRepository.findById(id)); } @Test public void deleteById_test(){ // given int id = 1; // when boardRepository.deleteById(id); // delete 쿼리 발동 // then System.out.println("deleteById_test : " + boardRepository.findAll().size()); } @Test public void findAllV3_test(){ List<Board> boardList = boardRepository.findAllV2(); System.out.println("findAllV3_test : 조회완료 쿼리 2번"); boardList.forEach(board -> { System.out.println(board); }); } @Test public void findAllV2_test(){ List<Board> boardList = boardRepository.findAllV2(); System.out.println("findAllV2_test : 조회완료 쿼리 2번"); boardList.forEach(board -> { System.out.println(board); }); } @Test public void findAll_inqueryv2_test() { String q = "SELECT DISTINCT b FROM Board b JOIN FETCH b.user"; List<Board> boards = em.createQuery(q, Board.class).getResultList(); for (Board board : boards) { System.out.println("Board ID: " + board.getId()); System.out.println("User ID: " + board.getUser().getId()); // 사용자(User) 객체에 대한 다른 정보도 필요하다면 추가 가능 } } @Test public void findAll_inquery_test() { // 보드에 해당하는 모든 사용자 ID 조회 String q1 = "SELECT DISTINCT b.user.id FROM Board b"; List<Integer> userIds = em.createQuery(q1, Integer.class).getResultList(); // 각 사용자 ID에 해당하는 보드를 찾아서 사용자 할당 for (Integer userId : userIds) { // 해당 사용자 ID에 해당하는 모든 보드를 찾기 String q2 = "SELECT b FROM Board b WHERE b.user.id = :userId"; List<Board> boards = em.createQuery(q2, Board.class) .setParameter("userId", userId) .getResultList(); // 해당 사용자 ID에 해당하는 사용자를 찾기 User user = em.find(User.class, userId); // 각 보드에 사용자 할당 및 결과 출력 for (Board board : boards) { board.setUser(user); System.out.println("Board ID: " + board.getId() + ", User ID: " + user.getId()); } } } @Test public void randomquery_test(){ int[] ids = {1,2}; // select u from User u where u.id in (?,?); String q = "select u from User u where u.id in ("; for (int i=0; i<ids.length; i++){ if(i==ids.length-1){ q = q + "?)"; }else{ q = q + "?,"; } } System.out.println(q); } @Test public void findAll_custom_inquery_test() { String q = "SELECT DISTINCT b.user.id FROM Board b"; List<Integer> userIds = em.createQuery(q, Integer.class).getResultList(); for (Integer userId : userIds) { System.out.println(userId); } } @Test public void findAll_LazyLoading_test() { // given // when List<Board> boardList = boardRepository.findAll(); boardList.forEach(board -> { System.out.println(board.getUser().getUsername()); }); // then } @Test public void findAll_test() { // given // when List<Board> boardList = boardRepository.findAll(); boardList.forEach(board -> { System.out.println(board.getUser().getUsername()); }); // then } @Test public void findByIdJoinUser_test() { int id = 1; boardRepository.findByIdJoinUser(id); } @Test public void findById_test() { int id = 1; System.out.println("start - 1"); Board board = boardRepository.findById(id); System.out.println("start - 2"); System.out.println(board.getUser().getId()); System.out.println("start - 3"); System.out.println(board.getUser().getUsername()); } }
notion image
notion image
 
notion image
 
 

3. BoardController 에 updateForm, update 수정하기

package shop.mtcoding.blog.board; import ch.qos.logback.core.model.Model; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpSession; 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 shop.mtcoding.blog.user.User; import java.lang.annotation.Native; import java.util.List; @RequiredArgsConstructor @Controller public class BoardController { private final BoardRepository boardRepository; private final HttpSession session; // @Transactional 트랜잭션 시간이 너무 길어져서 service에 넣어야함 @PostMapping("/board/{id}/update") public String update(@PathVariable Integer id, String title, String content) { boardRepository.updateById(id, title, content); return "redirect:/board/" + id; } @GetMapping("/board/{id}/update-form") public String updateForm(@PathVariable(name = "id") Integer id, HttpServletRequest request) { Board board = boardRepository.findById(id); request.setAttribute("board", board); return "/board/update-form"; // 서버가 내부적으로 index를 요청 - 외부에서는 다이렉트 접근이 안됨 } @PostMapping("/board/{id}/delete") public String delete(@PathVariable Integer id) { boardRepository.deleteById(id); return "redirect:/"; } @GetMapping("/") public String index(HttpServletRequest request) { List<Board> boardList = boardRepository.findAll(); request.setAttribute("boardList", boardList); return "index"; // 서버가 내부적으로 index를 요청 - 외부에서는 다이렉트 접근이 안됨 } @PostMapping("/board/save") public String save(BoardRequest.SaveDTO reqDTO) { User sessionUser = (User) session.getAttribute("sessionUser"); boardRepository.save(reqDTO.toEntity(sessionUser)); 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 = boardRepository.findByIdJoinUser(id); request.setAttribute("board", board); return "board/detail"; } }
 
  • view 수정하기
{{> /layout/header}} <div class="container p-5"> <!-- 요청을 하면 localhost:8080/board/save POST로 요청됨 title=사용자입력값&content=사용자값 --> <div class="card"> <div class="card-header"><b>글수정하기 화면입니다</b></div> <div class="card-body"> <form action="/board/{{board.id}}/update" method="post"> <div class="mb-3"> <input type="text" class="form-control" placeholder="Enter title" name="title" value="{{board.title}}"> </div> <div class="mb-3"> <textarea class="form-control" rows="5" name="content">{{board.content}}</textarea> </div> <button type="submit" class="btn btn-primary form-control">글수정하기완료</button> </form> </div> </div> </div> {{> /layout/footer}}
notion image
 
notion image
notion image
 

4. BoardRequest 에 UpdateDTO 만들기

package shop.mtcoding.blog.board; import lombok.Data; import shop.mtcoding.blog.user.User; public class BoardRequest { @Data public static class UpdateDTO { private String title; private String content; } @Data public static class SaveDTO { private String title; private String content; // DTO를 클라이언트로 부터 받아서, PC에 전달하기 위해 사용 // insert하는 DTO에서만 만들기 public Board toEntity(User user){ return Board.builder() .title(title) .content(content) .user(user) .build(); } } }
 

5. BoardController 에 update 수정하기

package shop.mtcoding.blog.board; import ch.qos.logback.core.model.Model; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpSession; 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 shop.mtcoding.blog.user.User; import java.lang.annotation.Native; import java.util.List; @RequiredArgsConstructor @Controller public class BoardController { private final BoardRepository boardRepository; private final HttpSession session; // @Transactional 트랜잭션 시간이 너무 길어져서 service에 넣어야함 @PostMapping("/board/{id}/update") public String update(@PathVariable Integer id, BoardRequest.UpdateDTO reqDTO) { boardRepository.updateById(id, reqDTO.getTitle(), reqDTO.getContent()); return "redirect:/board/" + id; } @GetMapping("/board/{id}/update-form") public String updateForm(@PathVariable(name = "id") Integer id, HttpServletRequest request) { Board board = boardRepository.findById(id); request.setAttribute("board", board); return "/board/update-form"; // 서버가 내부적으로 index를 요청 - 외부에서는 다이렉트 접근이 안됨 } @PostMapping("/board/{id}/delete") public String delete(@PathVariable Integer id) { boardRepository.deleteById(id); return "redirect:/"; } @GetMapping("/") public String index(HttpServletRequest request) { List<Board> boardList = boardRepository.findAll(); request.setAttribute("boardList", boardList); return "index"; // 서버가 내부적으로 index를 요청 - 외부에서는 다이렉트 접근이 안됨 } @PostMapping("/board/save") public String save(BoardRequest.SaveDTO reqDTO) { User sessionUser = (User) session.getAttribute("sessionUser"); boardRepository.save(reqDTO.toEntity(sessionUser)); 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 = boardRepository.findByIdJoinUser(id); request.setAttribute("board", board); return "board/detail"; } }
Share article

vosw1