springboot - blog project (28,29)

Yuri Lee·2020년 8월 25일
1

springboot - blog project

목록 보기
16/49

스프링부트 강좌 28강(블로그 프로젝트) - update 테스트

	// email, password
	@PutMapping("/dummy/user/{id}")
	public User updateUser(@PathVariable int id, @RequestBody User requestUser ) { //json 데이터를 요청 => Java Object(MessageConverter의 Jackson 라이브러리가 변환해서 받아줌)
		System.out.println("id : "+id);
		System.out.println("password : "+requestUser.getPassword());
		System.out.println("id : "+requestUser.getEmail());
		
		
		requestUser.setId(id);
		requestUser.setUsername("ssar");
		userRepository.save(requestUser);
		return null;
	}


sava 라는 함수는 원래 insert 할때 사용하는 것이다. 니가 만약 save를 할때 id 값을 넘겨주면 그 아이디 값이 만약 데이터베이스에 있다면 걔를 업데이트를 해준다. 근데 문제는 password, email, ssar만 있기 때문에 다른 값들이 null로 변해버리는 문제가 생긴다.

그래서 update 할때 save를 사용하지 않는다. 사용할 수는 있는데 .. 거의 안쓴다.

	// save 함수는 id를 전달하지 않으면 insert를 해주고
	// save 함수는 id를 전달하면 해당 id에 대한 데이터가 있으면 update를 해주고
	// save 함수는 id를 전달하면 해당 id에 대한 데이터가 없으면 insert를 한다. 
	// email, password
	@PutMapping("/dummy/user/{id}")
	public User updateUser(@PathVariable int id, @RequestBody User requestUser ) { //json 데이터를 요청 => Java Object(MessageConverter의 Jackson 라이브러리가 변환해서 받아줌)
		System.out.println("id : "+id);
		System.out.println("password : "+requestUser.getPassword());
		System.out.println("id : "+requestUser.getEmail());
		
		User user = userRepository.findById(id).orElseThrow(()-> {
			return new IllegalArgumentException("수정에 실패하였습니다.");
		});
		user.setPassword(requestUser.getPassword());
		user.setEmail(requestUser.getEmail());
	
		userRepository.save(requestUser);
		return null;
	}

그렇다면 이번에는 save 함수를 주석처리하고 @Transactional 를 넣어보자.

	@Transactional
	@PutMapping("/dummy/user/{id}")
	public User updateUser(@PathVariable int id, @RequestBody User requestUser ) { //json 데이터를 요청 => Java Object(MessageConverter의 Jackson 라이브러리가 변환해서 받아줌)
		System.out.println("id : "+id);
		System.out.println("password : "+requestUser.getPassword());
		System.out.println("id : "+requestUser.getEmail());
		
		User user = userRepository.findById(id).orElseThrow(()-> {
			return new IllegalArgumentException("수정에 실패하였습니다.");
		});
		user.setPassword(requestUser.getPassword());
		user.setEmail(requestUser.getEmail());
	
		// userRepository.save(requestUser);
		return null;
	}

put 요청을 postman을 이용하여 해보자.

save를 호출하지 않았는데 변경이 되어있음을 볼 수 있다...!!!

이는 더티체킹 때문이다.

스프링부트 강좌 29강(블로그 프로젝트) - 영속성 컨텍스트와 더티체킹

영속성 컨텍스트

----request---->
controller
<----response---

컨트롤러에서 어떤 요청을 받는다. 모든 요청은 컨트롤러에 모인다. 요청을 받고 응답을 해주는 형식이다.

요청을 받았을 때 Insert, update, delete, select 를 하기도 한다.

지금 user 라는 테이블을 만들었는데

user table
1|
2|
3|

JAP가 들고있는 영속성 컨텍스트라는 게 있다. 크기가 매우 크다. 우리가 만약에 insert를 한다고 치면 controleer에서 user 객체를 하나 만든다. 그리고 save를 한다. 그럼 영송성 컨텍스트 안에 1차 캐시라는게 있다.

1차 캐시에 user 객체가 쌓인다. 그리고 이 유저 객체가 하나 만들어져서 ...

만약 지금 user data가 3건이 있다고 치면 4가 딱 생기면서 새로운 객체가 들어간다.

1차 캐시에 유저라는 게 있는데 이것을 영속화 되었다고 말하고, 영속화된 객체를 데이터베이스에 밀어넣는 것을 flash라고 한다.

어떤 창고가 있다. 물건들이 꽉 찾다. 비워야 한다. 다른 물건을 채우려면, 이런 상황에서 물건들을 모두 큰 창고에 옮겨 놓으면 새로운 물건들을 받을 수 있을 것이다. 옮기고 원래 있던 창고를 비우는 것을 flash라고 한다.

프로그래밍에서는 버퍼를 비운다라고도 말한다. flash를 하면 1차 캐시에 있는 오브젝트를 데이터베이스에 밀어넣는데, 플러쉬긴 한데 비우진 않는다. 남아있는다.

이것을 남아놓고 사용한다.
만약 컨트롤러에서 select(4)를 한다. 첫번째로는 영속화되었는지 확인한다. 이때 오브젝트로 영속화가 되어있으면 굳이 데이터베이스에 접근하지 않고 그냥 들고온다.

그럼 실제 디비에 접근하지 않아서 부하가 적어질 수 있다. 이런 상황에서 내가 업데이트를 하고 싶다고 하자.
이번에 업데이트 하고 싶은 데이터가 2번 데이터의 password, email 업데이트하고 싶다고 하자.

1번. 2번 데이터를 select를 해서 데이터베이스에서 들고와서 영속화를 시킨다. 그럼 user가 쏙 들어올텐데... 이 오브젝트를 controller로 들고온다. 그러고 나서 영속화 된 오브젝트 유저 값을 변경한다.

다 끝나고 나서 이 유저 오브젝트를 변경된 값으로 변경하려면, save를 호출하면

2번 데이터의 password 랑 email이 변경이 되었다. 이 두개가 변경이 되었으니까 내가 지금 세이브 해서 밀어넣은 유저 오브젝트와 영속화 되어있는 영속화 오브젝트를 비교해봤더니 같은 아이디

근데 값이 패스워드와 이메일이 달라져있으니 영속화되어있는 오브젝트를 업데이트 한다. 그리고 이것을 디비에 flash 해서 밀어넣으면 디비 값이 변경된다. save 만 하면 자동으로 일어난다.

updateUser 이란 얘를 누군가 수정해달라고 요청을 했다. @Transactional라는 어노테이션을 붙여넣게 되면 데이터베이스 트랜젝션이 시작하게 되고, 언제 종료가 되냐면 updateUser 라는 메서드가 종료될 때 트랜잭션이 종료된다. 그럼 자동으로 트랜잭션이 종료되면서 무엇을 하냐면...함수 종료시에 자동 commit 이 된다.

영속화 시킨 후에 그 값을 변경 시키게 되면 변경을 감지하고, db에 수정을 날려준다. 이것을 더티 체킹이라고 한다.

-이 글은 유투버 겟인데어의 스프링 부트 강좌를 바탕으로 정리한 내용입니다.-

profile
Step by step goes a long way ✨

0개의 댓글