본문 바로가기

SpringBoot/Blog프로젝트 with JPA &데어프로그래밍님

21.1.4 TIL - JPA를 이용한 database update, delete, 영속성 컨텍스트와 더티체킹

※본 포스팅은 데어프로그래밍님 스프링부트 블로그프로젝트 강의 수강 후 작성한 내용입니다.

 

[데이터 update]

update를 할 때는 put request를 사용한다.

update를 하기위해 save함수를 사용할 수 도 있고 JPA더티체킹을 사용할 수 도 있다. 해당프로젝트에서는 더티체킹 방법을 사용하지만 save를 이용하는 방법도 살펴보자!

 

1)save를 이용한 update

save함수는 id를 전달하지 않거나 전달된 id에 대한 데이터가 DB에 없으면 insert를 한다. 만약 id가 주어지고 해당 id에 대한 데이터가 DB에 있는 경우 update를 수행한다. save를 이용해서 update를 하기위한 코드는(코드 일부분임) 아래와 같다.

User user = userRepository.findById(id).orElseThrow(()->{
	return new IllegalArgumentException("수정에 실패하였습니다.");
});
user.setPassword(requestUser.getPassword());
user.setEmail(requestUser.getEmail());
userRepository.save(user);

()-> 는 람다식을 이용한 것 이다. 람다식을 사용하지 않은 경우 Supplier interface를 override해서 사용. 

 

2)더티체킹을 이용한 update

더티체킹이 무엇인지 설명하기 전에 JPA의 영속성 컨텍스트에 대해 먼저 간단하게 알아보자.

영속성이란? 어떤 데이터를 영구적으로 저장하게 해주는 것이다. 자바에서는 데이터를 영구적으로 저장하기 위해 DB를 사용한다. 

컨텍스트라는 것은 정보를 가지고 있는 것이다. 예를 들어 어떤 대상의 모든 컨텍스트를 가지고 있다는 것은 그 대상의 모든 정보를 알고 있다는 뜻이다.

둘을 합쳐서 생각해보면 영속성 컨텍스트란 자바가 DB에 저장해야되는 모든것을 알고 있는 것이다.

자바가 DB에 데이터를 저장하려고 하면 DB에 바로 던지는 것이 아니라 JPA의 영속성 컨텍스트에 먼저 데이터를 던진다. 이렇게 영속성 컨텍스트에 들어간 데이터를 영속화 되었다고 한다. 그리고 영속성 컨텍스트에서 데이터를 DB에 던지게 된다.(커밋한다) 이때 영속성 컨텍스트에 있는 데이터의 타입은 자바 오브젝트이고 DB에 들어있는 데이터는 데이터베이스에 맞는 타입이다. 만약 영속성 컨텍스트에 있는 데이터를 삭제하고 DB에 commit하게 되면 DB에 있는 데이터도 삭제된다. (영속성 컨텍스트의 데이터와 DB의 데이터가 동기화 된다.) 

더티체킹이란? update를 위해 DB에서 데이터를 찾아서 영속성 컨텍스트로 가져오고 자바로 가지고 왔다고 하자. 자바에서 데이터를 수정하면 영속성 컨텍스트에 있는 데이터와 id는 같지만 정보는 달라진 것을 JPA가 확인하고 기존에 영속화 된 데이터를 수정한다. 이를 더티체킹이라고 한다.

그리고 @Transactional 어노테이션을 달아두면 method가 끝날 때 commit되는데 이때 영속성 컨텍스트에 있는 데이터와 DB의 데이터가 다르기 때문에 update가 자동으로 실행된다.

 

@Transactional을 사용하여 update를 하는 코드를 보면 아래와 같다.

	@Transactional 
	@PutMapping("dummy/user/{id}")
	public User updateUser(@PathVariable int id, @RequestBody User requestUser) {
		System.out.println("id :"+id);
		System.out.println("password :"+requestUser.getPassword());
		System.out.println("email :"+requestUser.getEmail());
		
		//findById해서 db에서 들고올 때 user객체가 영속화 된다.
		User user = userRepository.findById(id).orElseThrow(()->{
			return new IllegalArgumentException("수정에 실패하였습니다.");
		});
		user.setPassword(requestUser.getPassword());
		user.setEmail(requestUser.getEmail());

		return user;
	}

@PutMapping의 주소가 이전에 만들어둔 user상세보기 페이지의 주소와 같은데 request방법이 다르기 때문에 알아서 구분해주기 때문에 상관없다. 

@RequestBody는 json데이터를 받기 위해 사용한다. postman으로 request 테스트를 할 때 put방법으로 하고 body에서 raw - json을 선택해서 수정하려는 데이터를 보낸다. 받은 json데이터는 JPA의 Message Converter의 Jackson라이브러리가 자바 오브젝트로 변환해서 받아준다. 이를 수행하도록 하는 것이 @RequestBody이다.

 

[데이터 delete]

데이터를 delete하기 위해서는 Delete request를 해야한다. 데이터삭제는 JpaRepository의 deleteById를 사용하고 추가적으로 요청받은 id가 DB에 없을 경우 에러처리만 해주면 된다.

	@DeleteMapping("/dummy/user/{id}")
	public String deleteUser(@PathVariable int id) {
		try {
			userRepository.deleteById(id);
		} catch (EmptyResultDataAccessException e) {
			return "삭제에 실패하였습니다. 해당 id는 DB에 없습니다.";
		}
		return "삭제되었습니다. id :"+id;
	}

 

댓글