
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;

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);
}
}

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";
}
}

Share article