게시판 프로젝트 - Board 수정 상황
사용자가 수정 html에서 데이터를 입력하면 백엔드에서 dto로 해당 데이터를 받아 Board 데이터를 수정한다.
1. Entity
@Getter
@Entity
@ToString
@NoArgsConstructor(access = AccessLevel.PROTECTED)
public class Board {
@Id @GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "board_id")
private Long id;
@NotBlank
private String title;
@NotBlank
private String content;
@NotBlank
private String password;
@CreatedDate
private LocalDateTime createdAt;
public Board(String password, String title, String content) {
this.password = password;
this.title = title;
this.content = content;
createdAt = LocalDateTime.now();
}
public void update(String title, String content) {
this.title = title;
this.content = content;
}
}
2. 수정 DTO
@Data
@NoArgsConstructor
@AllArgsConstructor
public class BoardUpdateDto {
private String title;
private String content;
}
핵심 : JPA의 변경 감지는 반드시 트랜잭션 안에서 발생한다.
수정 로직 - 잘못된 예시
@PostMapping("/update/{boardId}")
public String updateBoard(@PathVariable Long boardId,
@ModelAttribute BoardUpdateDto dto) {
// 변경 감지로 update
Board board = boardService.readDetail(boardId); // 변경하려는 board 조회
board.update(dto.getTitle(), dto.getContent()); // 변경
return "redirect:/board/" + boardId;
}
board.update로 데이터를 변경하지만 "트랜잭션" 안에서 데이터를 변경하지 않기 때문에 DB에서 실제로 데이터 변경이 일어나지 않는다.
수정 로직 - 올바른 예시
// 컨트롤러 엔드 포인트
@PostMapping("/update/{boardId}")
public String updateBoard(@PathVariable Long boardId,
@ModelAttribute BoardUpdateDto dto) {
// 변경 감지로 update
Board board = boardService.update(boardId, dto);
return "redirect:/board/" + boardId;
}
// 서비스 계층 메서드 : @Transactional - 트랜잭션 안에서 변경 감지를 다룬다..
@Transactional
public Board update(Long boardId, BoardUpdateDto dto) {
Board findBoard = boardRepository.findById(boardId).orElse(null);
if (findBoard == null) {
throw new NoSuchElementException("No Board Data");
}
// 영속성 컨텍스트에서 영속화된 엔티티를 확인 후 변경이 있다면 쓰기 지연 저장소에 update 쿼리를 넣는다.
// 트랜잭션 종료 시 쓰기 지연 저장소의 update 쿼리가 DB에 전달된다.
findBoard.update(dto.getTitle(), dto.getContent());
return findBoard;
}
// 리포지토리
@Repository
public interface BoardRepository extends JpaRepository<Board, Long> {
}
@Transactional
public Board update(Long boardId, BoardUpdateDto dto) {
Board findBoard = boardRepository.findById(boardId).orElse(null);
if (findBoard == null) {
throw new NoSuchElementException("No Board Data");
}
// 영속성 컨텍스트에서 영속화된 엔티티를 확인 후 변경이 있다면 쓰기 지연 저장소에 update 쿼리를 넣는다.
// 트랜잭션 종료 시 쓰기 지연 저장소의 update 쿼리가 DB에 전달된다.
findBoard.update(dto.getTitle(), dto.getContent());
return findBoard;
}
트랜잭션 안에서 데이터를 변경하기 때문에 데이터 변경 시점에 영속성 컨텍스트에서 변경 감지를 확인 후 쓰기 지연 저장소에 update SQL을 넣어둔다.
트랜잭션이 종료되는 시점에 쓰기 지연 저장소들의 쿼리를 DB에 전달하여 수정을 반영한다.
'Java & Spring > JPA' 카테고리의 다른 글
| [Spring Data Jpa] 스프링 부트 페이징 처리 (0) | 2026.04.25 |
|---|---|
| [Spring] JPA 5 (1) | 2026.03.03 |
| [Spring] JPA 4 (0) | 2026.02.12 |
| [Spring] JPA 3 (0) | 2026.02.05 |
| [Spring] JPA 2 (0) | 2026.01.28 |