OS : MacOs Mojave
DB : MySQL 5.7
DB Tool : Sequel Pro
Framework : Spring Boot 2.0
맨밑에 결론있음
1. 준비
다음과 같은 member Entity를 준비했다.
public class Member {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "id")
private Long id;
@Column(name = "uuid")
private String uuid;
@Column(name = "name")
private String name;
}
2. @Transactional 없이 save와 saveAndFlush 비교
1. save or saveAndFlush 이후의 set을 통한 변경
각각 return 문에 break point를 걸고 수행해 보았다.
1. save 한 후 set 할 경우
public Member createMember(MemberRequest request) {
Member member = Member.create(request);
member = memberRepository.save(member);
member.setName("ChangeName");
return member;
}
breakpoint 에서는
Hibernate:
insert
into
member
(created_at, last_login, name, uuid)
values
(?, ?, ?, ?)
해당 메소드 수행이 종료될 때
DB 에 바뀐 name이 값으로 들어가지 않는다.
2. saveAndFlush 하고 set할 경우 에는
public Member createMember2(MemberRequest request) {
Member member = Member.create(request);
member = memberRepository.saveAndFlush(member);
member.setName("ChangeNameFlush");
return member;
}
해당 메소드 수행이 종료될 때
DB 에 바뀐 name이 값으로 들어가지 않는다.
2. save or saveAndFlush 이후의 set을 통한 변경 후 다시 save or saveAndFlush
3. save 한 후 set 하고 또 다시 save 할 경우
public Member createMember(MemberRequest request) {
Member member = Member.create(request);
member = memberRepository.save(member);
member.setName("ChangeName");
return memberRepository.save(member);
}
해당 메소드 수행이 종료될 때
4. saveAndFlush 한 후 set 하고 또 다시 saveAndFlush 할 경우
public Member createMember2(MemberRequest request) {
Member member = Member.create(request);
member = memberRepository.saveAndFlush(member);
member.setName("ChangeNameFlush");
return memberRepository.saveAndFlush(member);
}
해당 메소드 수행이 종료될 때
3. @Transactional 있는 상태에서 save와 saveAndFlush 비교
1. save or saveAndFlush 이후의 set을 통한 변경
1. save 한 후 set 할 경우
@Transactional
public Member createMember(MemberRequest request) {
Member member = Member.create(request);
member = memberRepository.save(member);
member.setName("ChangeName");
return member;
}
해당 메소드 수행이 종료될 때
1. saveAndFlush 한 후 set 할 경우
@Transactional
public Member createMember2(MemberRequest request) {
Member member = Member.create(request);
member = memberRepository.saveAndFlush(member);
member.setName("ChangeNameFlush");
return member;
}
해당 메소드 수행이 종료될 때
2. save or saveAndFlush 이후의 set을 통한 변경 이후 save or saveAndFlush
3. save 한 후 set 하고 또 다시 save 할 경우
이렇게 하고 각각 최초 save 문을 제외하고 breakpoint 를 걸었다.
첫번째 breakpoint
Hibernate:
insert
into
member
(created_at, last_login, name, uuid)
values
(?, ?, ?, ?)
console 출력 / DB업데이트 안됨
두번째 breakpoint
console 출력 없음 / DB 업데이트 안됨
세번째 breakpoint (return문)
console 출력 없음 / DB 업데이트 안됨
메소드 종료 후
Hibernate:
update
member
set
created_at=?,
last_login=?,
name=?,
uuid=?
where
id=?
console 출력 / DB 업데이트
4. saveAndFlush 한 후 set 하고 또 다시 saveAndFlush 할 경우
@Transactional
public Member createMember2(MemberRequest request) {
Member member = Member.create(request);
member = memberRepository.saveAndFlush(member);
member.setName("ChangeNameFlush");
member = memberRepository.saveAndFlush(member);
member.setName("ChangeNameFlush2");
member = memberRepository.saveAndFlush(member);
member.setName("ChangeNameFlush3");
return member;
}
첫번째 breakpoint
Hibernate:
insert
into
member
(created_at, last_login, name, uuid)
values
(?, ?, ?, ?)
console 출력 / DB업데이트 안됨
두번째 breakpoint
Hibernate:
update
member
set
created_at=?,
last_login=?,
name=?,
uuid=?
where
id=?
console 출력 / DB업데이트 안됨
세번째 breakpoint (return문)
Hibernate:
update
member
set
created_at=?,
last_login=?,
name=?,
uuid=?
where
id=?
console 출력 / DB업데이트 안됨
메소드 종료 후
console 출력 / DB 업데이트
결론
위의 여러가지 동작 방식으로 알 수 있었던 점은
JpaRepository의 saveAndFlush에 있는 Flush 는 DB에 업데이트를 하는 Flush 가 아니라
다음과 같은 그림에서 Context내에 Query Space (임의로 지정한 이름입니다) 로 flush를 하는 과정이라고 생각된다.
saveAndFlus로 업데이트를하면 매번 query를 queryspace에 보내고 그걸 트랜잭션 종료시점에 db에 업데이트를 하고
save를 하면 마지막에 context에 존재하는 형태의 데이터를 query로 만들어서 트랙잭션 종료시점에 db에 업데이트 하게 되는 것이다.
따라서 효율성 측면에서 saveAndFlush 보다는 save를 추천한다.
끝!
'JPA' 카테고리의 다른 글
[JPA] JPAQuery 에서 Pageable(offset,limit,orderby) 사용하기 (0) | 2023.06.21 |
---|---|
[JPA] @Convert 사용해서 Object를 Json 형식으로 저장하기 (0) | 2019.12.11 |
[JPA] Differences between save() And saveAndFlush() of SpringJPA (0) | 2018.11.10 |
[JPA] JPA시작하기 - JPA란? (1) | 2017.02.02 |