본문 바로가기

Back-End/JPA

Spring jpa save(), saveAndFlush() 제대로 알고 쓰기

@Transactional 없이 save() vs saveAndFlush()

public Member saveMember(MemberDTO memberDTO){
	Member member = Member.create(memberDTO);
    member = memberRepository.save(member);
    member.setName("TaeHyun");
    return member;	// break point 설정
}

아래와 같이 console에 출력되지만 변경된 name(태현) 은 입력되지 않는다.

Hibernate :
	insert
    into
    	member
        (name, uuid ... )
   	values
    	(?,?, ... )

public Member saveMember(MemberDTO memberDTO){
	Member member = Member.create(memberDTO);
    member = memberRepository.saveAndFlush(member);
    member.setName("TaeHyun");
    return member;	// break point 설정
}

아래와 같이 console에 출력되지만 변경된 name(태현) 은 입력되지 않는다.

Hibernate :
	insert
    into
    	member
        (name, uuid ... )
   	values
    	(?,?, ... )

@Transactional 있는 상태에서 save() vs saveAndFlush()

@Transactional
public Member saveMember(MemberDTO memberDTO){
	Member member = Member.create(memberDTO);
    member = memberRepository.save(member);
    member.setName("TaeHyun");
    return member;	// break point 설정
}
@Transactional
public Member saveMember(MemberDTO memberDTO){
	Member member = Member.create(memberDTO);
    member = memberRepository.saveAndFlush(member);
    member.setName("TaeHyun");
    return member;	// break point 설정
}

둘다 breakpoint까지는 update 되지 않지만 함수가 종료된 후에 update가 된다. 결국 여기까지도 두개다 같은 동작을 한다. 그렇다면 도대체 뭐가 차이 일까?

 

@Transactional 있는 상태에서 save() vs saveAndFlush() 후 set을 여러번 하는 경우

각각 save 문 뒤에 breakpoint를 설정했는데 어떻게 될까? save 할때마다 update 문이 날아갈까?

@Transactional
public Member saveMember(MemberDTO memberDTO){
	Member member = Member.create(memberDTO);
    member = memberRepository.save(member);
    member.setName("TaeHyun");
    member = memberRepository.save(member);
    member.setName("TaeHyun2");
    member = memberRepository.save(member);
    member.setName("TaeHyun3");
    return member;	// break point 설정
}
  • 첫번째 breakpoint : insert query 출력 / db 업데이트 안됨
  • 두번째 breakpoint : query 출력 없음 / db 업데이트 안됨
  • 세번째 breakpoint : query 출력 없음 / db 업데이트 안됨
  • 메소드 종료 후 : update query 출력 / db 업데이트 됨

즉, 실제 디비에 update는 TaeHyun3만 된 것이다.

 

@Transactional
public Member saveMember(MemberDTO memberDTO){
	Member member = Member.create(memberDTO);
    member = memberRepository.saveAndFlush(member);
    member.setName("TaeHyun");
    member = memberRepository.saveAndFlush(member);
    member.setName("TaeHyun2");
    member = memberRepository.saveAndFlush(member);
    member.setName("TaeHyun3");
    return member;	// break point 설정
}
  • 첫번째 breakpoint : insert query 출력 / db 업데이트 안됨
  • 두번째 breakpoint : update query 출력  / db 업데이트 안됨
  • 세번째 breakpoint : update query 출력  / db 업데이트 안됨
  • 메소드 종료 후 : update query 출력 / db 업데이트 됨
Hibernate:
	update
    	member
    set
    	name=?,
        ...
    where
    	id=?

 

결론

saveAndFlush()라고 해서 바로 db에 업데이트를 하는 flush가 아니라 쓰기 지연 SQL 저장소 내로 flush를 하는 과정인거 같다. 어째뜬, 효율성 측면에서는 saveAndFlush() 보다는 save()를 권장하는 것 같다.