본문 바로가기

개발/프로젝트

[스프링부트 게시판] 10. JPA UPDATE

이번 게시글에서는 데이터를 전달 받아 해당 사용자의 정보를 수정하는 UPDATE 작업을 수행하도록 하겠습니다.

 

우선 UserController 클래스에 다음과 같이 함수를 구현하였습니다.

 

[UserController]

@PutMapping("/user/{id}")
public void update(@PathVariable Long id, @RequestBody User requestUser) {
    User user = userRepository.findById(id).orElseThrow(() -> {
        // IllegalArgumentException 예외 처리
        throw new IllegalArgumentException("해당하는 아이디가 없습니다 id : " + id);
    });

    user.setPassword(requestUser.getPassword());
    user.setEmail(requestUser.getEmail());

    userRepository.save(user);
}

 

Update 작업을 수행하기 때문에 Http Request에 수정을 담당하는 Put에 해당하는 @PutMapping 어노테이션으로 진행하였습니다. Jpa에 특징으로는 INSERT 작업 할때 save를 사용했다는 점인데 save 함수에는 이러한 특징이 들어있습니다.

  • id를 전달하지 않을 경우 Insert 수행
  • id를 전달할 경우 해당 id에 대한 데이터가 있다면 Update 수행
  • id를 전달할 경우 해당 id에 대한 데이터가 없다면 Insert 수행

 

즉, id의 값을 먼저 SELECT로 확인을 하고 데이터가 존재한다면 user에 setter 작업을 통해 값을 변경 시킨 후 save 함수를 거쳐 UPDATE 작업이 진행됩니다.

 

Postman을 통해 Put 요청을 수행하는데, 이 때 요청하는 데이터를 JSON 형식의 MIME 타입을 갖도록 해야합니다.

 

Postman
DBeaver

 

정상적으로 수정된 값이 들어갔습니다. 그리고 전에 작성해 놓은 수정일(modDt)@LastModifiedDate를 통해 UPDATE 작업한 시간에 맞게 값이 새로 들어온 것을 확인 하실 수 있습니다.

 

save 함수로 사용이 가능하지만 어노테이션을 활용하여 수정하는 방법도 있습니다.

 

@Transactional
@PutMapping("/user/{id}")
public void update(@PathVariable Long id, @RequestBody User requestUser) {
    User user = userRepository.findById(id).orElseThrow(() -> {
        // IllegalArgumentException 예외 처리
        throw new IllegalArgumentException("해당하는 아이디가 없습니다 id : " + id);
    });

    user.setPassword(requestUser.getPassword());
    user.setEmail(requestUser.getEmail());

    // userRepository.save(user);
}

 

save 함수를 주석처리를 하고 대신 @Transactional 어노테이션이 작성되었습니다.

 

먼저 트랜잭션(Transaction)에 대해 설명드리고자 합니다.

  • 데이터베이스의 상태를 변경하는 작업 또는 한번에 수행되어야 하는 연산들을 의미한다.
  • begin, commit 을 자동으로 수행해준다.
  • 예외 발생 시 rollback 처리를 자동으로 수행해준다.
  • 원자성(Automicity), 일관성(Consistency), 격리성(Isolation), 영속성(Durability)의 4가지 속성을 가진다.

이를 활용한 어노테이션이 @Transactional 어노테이션인데 이것이 가능한 이유는 더티 체킹(Dirty Checking)이란 '상태의 변화가 생긴 정도를 확인하는 검사' 입니다.

 

더티 체킹 (Dirty Checking)이란?

Spring Data Jpa와 같은 ORM 구현체를 사용하다보면 더티 체킹이란 단어를 종종 듣게 됩니다. 더티 체킹이란 단어를 처음 듣는분들을 몇번 만나게 되어 이번 시간엔 더티 체킹이 무엇인지 알아보겠습

jojoldu.tistory.com

 

JPA에서는 트랜잭션이 끝나는 시점에 변화가 있는 모든 엔티티 객체를 데이터베이스에 자동으로 반영해줍니다. 최초 조회 상태에서 변화가 있다는 것이 조건입니다.

JPA에서는 엔티티를 조회하면 해당 엔티티의 조회 상태 그대로 스냅샷을 만들어놓습니다.
그리고 트랜잭션이 끝나는 시점에는 이 스냅샷과 비교해서 다른점이 있다면 Update Query를 데이터베이스로 전달합니다.

 

당연히 이런 상태 변경 검사의 대상은 영속성 컨텍스트가 관리하는 엔티티에만 적용 됩니다.

  • detach된 엔티티 (준영속)
  • DB에 반영되기 전 처음 생성된 엔티티 (비영속)

등 준영속/비영속 상태의 엔티티는 Dirty Checking 대상에 포함되지 않습니다.
즉, 값을 변경해도 데이터베이스에 반영되지 않는다는 것입니다.

 

Postman
Console
DBeaver

 

위와 같이 정상적으로 save 함수 없이도 더티 체크(Dirty Check)를 통한 수정이 진행되었습니다.