티스토리 뷰

앞선 포스팅에서 더미 데이터를 Select 해오고, Insert 해보는 작업을 해봤다. 오늘은 Update 작업을 해볼 건데 앞선 Select와 Insert의 구현 방식을 이해했다면 손쉽게 이해할 수 있을 것이다.

 

# 1

  • 첫 번째로 생각해야할 것은 바로 DB의 Update를 위해서는 PostMaping을 한다는 것!
  • 그리고는 어떤 컬럼을 기준으로 Update문을 작성하고, 구현해야하는지. . . . 우리는 ID값을 기준으로 DB를 Update 할 것이다.

이제는 뭐 자동적으로 코드가 술술 나온다 ~ Update를 위한 PostMapping 주소를 입력하고, 매개변수로 @PathVariable을 사용해 id 값을 매칭시키고, @RequestBody 어노테이션을 사용해서 requestUser 라는 이름의 User 객체를 받는다. 이때 우리는 Json 데이터를 요청하지만 Message Converter의 Jackson 라이브러리가 자동으로 Java Object 즉, Java의 객체로 변환시켜 준다는 사실~

PostMan으로 Mapping 데이터를 추가한 후, 데이터가 잘 이동 되고 받아지는지 확인해본다.

// Update를 위한 PostMapping
@PostMapping("dummy/user/{id}")
public User userUpdate(@PathVariable int id @RequestBody User requestUser){

    System.out.println("id : " + id);
    
    System.out.println("email : " + requestUser.getEmail());
    
    System.out.println("password : " + requestUser.getPassword());

}

 

# 2

  • 데이터가 잘 이동되는 것을 확인했다면, 예외를 확인해봐야한다. 현재 우리는 ID값을 기준으로 매핑하고 있는데, 없는 ID를 기준으로 데이터를 전송(Post)하면 이것에 마땅한 예외처리를 해줘야한다.

현재 우리는 @PathVariable을 통해서 id 값을 받고 있고, 그 id 값을 userRepository 인터페이스에 내장된 findById() 메서드를 이용해서 찾아볼 때 그 id 값이 서칭되지 않는다면 예외를 처리해 줘야 한다. 오늘은 람다식을 활용해서 처리를 해줄 예정이다.

 

// Update를 위한 PostMapping
@PostMapping("dummy/user/{id}")
public User userUpdate(@PathVariable int id @RequestBody User requestUser){

    System.out.println("id : " + id);
    
    System.out.println("email : " + requestUser.getEmail());
    
    System.out.println("password : " + requestUser.getPassword());
    
    User user = userRepository.findById(id).orElseThrow(()->{
    	return new IllegalArgumentException("수정에 실패하였습니다.");
    )};
    
    // User 객체의 Email의 값을 @requestBody 어노테이션을 활용하여 받은 데이터로 변경
    User.setEmail(requestUser.getEmail());
    
    // User 객체의 Email의 값을 @requestBody 어노테이션을 활용하여 받은 데이터로 변경
    User.setPassword(requestUser.getPassword());
}

# 3

  • 모든 값들은 저장됐고, 이제는 값을 Commit만 해주면 되는 상황. userRepository.save() 메소드를 통해서 값을 Commit 해주는게 보통 상황이지만, 이번에 우리는 더티 체킹을 통해서 값을 커밋해주도록 하겠다.
  • 더티 체킹을 위해서는 @Transactional 어노테이션을 활용해야한다.
// 더티 체킹을 위한 @Transactioal
@Transactional
// Update를 위한 PostMapping
@PostMapping("dummy/user/{id}")
public User userUpdate(@PathVariable int id @RequestBody User requestUser){

    System.out.println("id : " + id);
    
    System.out.println("email : " + requestUser.getEmail());
    
    System.out.println("password : " + requestUser.getPassword());
    
    User user = userRepository.findById(id).orElseThrow(()->{
    	return new IllegalArgumentException("수정에 실패하였습니다.");
    )};
    
    // User 객체의 Email의 값을 @requestBody 어노테이션을 활용하여 받은 데이터로 변경
    user.setEmail(requestUser.getEmail());
    
    // User 객체의 Email의 값을 @requestBody 어노테이션을 활용하여 받은 데이터로 변경
    user.setPassword(requestUser.getPassword());
    
    // 더티 체킹을 위한 주석
    userRepository.save(user);
    
    return null;
}

# JPA 영속성 컨텍스트 / 더티 체킹

Update는 성공적으로 끝났지만, 더티 체킹(Dirty Checking)이 도대체 무엇인지 살펴보자.

더티 체킹을 이해하기 위해서는 먼저 JPA의 영속성 컨텍스트를 이해해야한다.

이해를 돕기 위해 내 완벽한 손 그림 필기를 보여주며 설명하도록 하겠다.

Controller는 Response와 Requset를 지속적으로 수행하고 User DB가 존재하고 JPA 영속성 컨텐스트가 이렇게 존재하자고 생각하자.

그 뒤로 우리가 Insert를 하려고 Controller 내에 User 객체를 만들어서 Save()를 하면 JPA 영속성 컨텍스트에서는 1차 캐시가 만들어지고 1차 캐시에 User 객체가 먼저 생성되고 그 후에 User DB에 데이터를 Insert 하는데, 여기서 1차 캐시에 User 객체가 생성되어 있는 모습을 영속화라고 한다. 다음과 같이 생성된다.

여기서 중요한점은 1차 캐시에 존재하는 데이터를 DB에 넣어주는 그 때의 작업을 Flush라고 하는데, 이 Flush 후에도 1차 캐시 속에는 user객체가 남아있다는 것이다. 그리고 다음 select 작업으로 user객체가 필요할 땐, DB에 바로 가는것이 아니라 1차 캐시에 들려, 1차 캐시에 user객체가 존재 한다면, DB에 가는 것이 아니라 1차 캐시에서 데이터들 끌어와 부하를 줄여준다. 그럼 똑같은 관점에서 update를 하려고 하면 어떻게 될까? 먼저 업데이트 하려는 ID값을 불러와 1차 캐시에 존재시키고, 1차 캐시에 존재하는 데이터와 update하려는 데이터가 다를 경우 1차 캐시에 존재하는 data를 똑같이 바꿔준 후, DB에 Flush해준다. 여기서 @Transactional 어노테이션의 역할로 인해서 메소드가 종료될 때 자동으로 Commit 해주면서, 영속성 컨텍스트의 변경내용을 데이터베이스에 자동으로 동기화 시켜주는 역할을 하고 변경을 감지해서 DB에 수정을 날려주는 것을 더티 체킹(Dirty Checking)이라고 한다. 그래서 위의 Update 작업에서 userRepository.save(user) 없이도 자동으로 변화를 감지하여 더티 체킹 해 준것이다.


# 마무리 

JPA를 공부할 때 가장 중요한게

객체와 관계형 데이터베이스를 매핑하는 것(Object Relational Mapping)

영속성 컨텍스트를 이해하는 것이라고 한다.

 

더티체킹(Dirty Checking)이란 상태 변경 검사이다.

JPA에서는 트랜잭션이 끝나는 시점에 변화가 있는 모든 엔티티 객체를 데이터베이스 반영한다.

그렇기 때문에 값을 변경한 뒤, save 하지 않더라도 DB에 반영되는 것이다.

이러한 상태 변경 검사의 대상은 영속성 컨텍스트가 관리하는 엔티티에만 적용된다.(준영속, 비영속된 객체X)

더티체킹(Dirty Checking) 원리: · 영속성 컨텍스트란 서버와 DB사이에 존재한다. 

JPA는 엔티티를 영속성 컨텍스트에 보관할 때, 최초 상태를 복사해서 저장해둔다.

(일종의 스냅샷) · 트랜잭션이 끝나고 flush할 때 스냅샷과 현재 엔티티를 비교해 변경된 엔티티를 찾아낸다.

JPA는 변경된 엔티티를 DB단에 반영하여 한번에 쿼리문을 날려준다.

댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
링크