본문 바로가기


JPA

[JPA] Differences between save() And saveAndFlush() of SpringJPA

OS : MacOs Mojave

DB : MySQL 5.7

DB Tool : Sequel Pro

Framework : Spring Boot 2.0


You can see conclusion at bottom of content 

1. Preparation

I created a 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. Compare save and saveAndFlush without @Transactional

1. After save() or saveAndFlush(). change value by setMethod

I tried to put breakpoint on the return statement.

1. Change value after save()

public Member createMember(MemberRequest request) {
Member member = Member.create(request);
member = memberRepository.save(member);
member.setName("ChangeName");
return member;
}
On breakpoint

Hibernate: 

    insert 

    into

        member

        (created_at, last_login, name, uuid) 

    values

        (?, ?, ?, ?)

The above message is output of console / DB was updated

When Method is finished

Changing name is not worked

2. Change value after saveAndFlush()

public Member createMember2(MemberRequest request) {
Member member = Member.create(request);
member = memberRepository.saveAndFlush(member);
member.setName("ChangeNameFlush");
return member;
}
On breakpoint
Hibernate: 
    insert 
    into
        member
        (created_at, last_login, name, uuid) 
    values
        (?, ?, ?, ?)
The above message is output of console / DB was updated

When Method is finished

Changing name is not worked


2. After save() or saveAndFlush(). change value by setMethod. and save() or saveAndFlush() again

I tried to put breakpoint on the return statement.

3. save() -> change value -> save()


public Member createMember(MemberRequest request) {
Member member = Member.create(request);
member = memberRepository.save(member);
member.setName("ChangeName");
return memberRepository.save(member);
}
On breakpoint
Hibernate: 
    insert 
    into
        member
        (created_at, last_login, name, uuid) 
    values
        (?, ?, ?, ?)
The above message is output of console / DB was updated

When Method is finished

Hibernate: 

    update
        member 
    set
        created_at=?,
        last_login=?,
        name=?,
        uuid=? 
    where
        id=?
The above message is output of console / DB was updated

4. saveAndFlush() -> change value -> saveAndFlush()

public Member createMember2(MemberRequest request) {
Member member = Member.create(request);
member = memberRepository.saveAndFlush(member);
member.setName("ChangeNameFlush");
return memberRepository.saveAndFlush(member);
}
On breakpoint
Hibernate: 
    insert 
    into
        member
        (created_at, last_login, name, uuid) 
    values
        (?, ?, ?, ?)
The above message is output of console / DB was updated

When Method is finished
Hibernate: 
    update
        member 
    set
        created_at=?,
        last_login=?,
        name=?,
        uuid=? 
    where
        id=?
The above message is output of console / DB was updated



The result is same

3. Compare save and saveAndFlush with @Transactional

1. After save() or saveAndFlush(). change value by setMethod

1. save() -> change value

@Transactional
public Member createMember(MemberRequest request) {
Member member = Member.create(request);
member = memberRepository.save(member);
member.setName("ChangeName");
return member;
}
On breakpoint
Hibernate: 
    insert 
    into
        member
        (created_at, last_login, name, uuid) 
    values
        (?, ?, ?, ?)
The above message is output of console / DB wasn't updated

When Method is finished

Hibernate: 

    update
        member 
    set
        created_at=?,
        last_login=?,
        name=?,
        uuid=? 
    where
        id=?
The above message is output of console / DB was updated with new name

1. saveAndFlush() -> change value

@Transactional
public Member createMember2(MemberRequest request) {
Member member = Member.create(request);
member = memberRepository.saveAndFlush(member);
member.setName("ChangeNameFlush");
return member;
}
On breakpoint
Hibernate: 
    insert 
    into
        member
        (created_at, last_login, name, uuid) 
    values
        (?, ?, ?, ?)
The above message is output of console / DB wasn't updated

When Method is finished

Hibernate: 

    update
        member 
    set
        created_at=?,
        last_login=?,
        name=?,
        uuid=? 
    where
        id=?
The above message is output of console / DB was updated with new name

2. After save() or saveAndFlush(). change value by setMethod. and save() or saveAndFlush() again

3. save() -> change value -> save()

I set breakpoint on each save() statement and return statement except first save()
@Transactional
public Member createMember(MemberRequest request) {
Member member = Member.create(request);
member = memberRepository.save(member);
member.setName("ChangeName");
member = memberRepository.save(member);
member.setName("ChangeName2");
member = memberRepository.save(member);
member.setName("ChangeName3");
return member;
}


On frist breakpoint

Hibernate: 

    insert 

    into

        member

        (created_at, last_login, name, uuid) 

    values

        (?, ?, ?, ?)

The above message is output of console / DB wasn't updated

On second breakpoint

No output /  DB wasn't updated


On third breakpoint (return statement)

No output /  DB wasn't updated


When Method is finished

Hibernate: 

    update

        member 

    set

        created_at=?,

        last_login=?,

        name=?,

        uuid=? 

    where

        id=?

The above message is output of console / DB was updated with new name


4.  saveAndFlush() -> change value -> 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;
}

On frist breakpoint

Hibernate: 

    insert 

    into

        member

        (created_at, last_login, name, uuid) 

    values

        (?, ?, ?, ?)

The above message is output of console / DB wasn't updated

On second breakpoint

Hibernate: 

    update

        member 

    set

        created_at=?,

        last_login=?,

        name=?,

        uuid=? 

    where

        id=?

The above message is output of console / DB wasn't updated

On third breakpoint (return statement)

Hibernate: 

    update

        member 

    set

        created_at=?,

        last_login=?,

        name=?,

        uuid=? 

    where

        id=?

The above message is output of console / DB wasn't updated

When Method is finished

The above message is output of console / DB was updated with new name



Conclusion

The conclusion about the above various operation methods
Flush of saveAndFlush() dose not mean Flush to update DB,
It is considered to be a process of flushing with Query Space (with arbitrarily name) in Context in the following figure.
When updating to saveAndFlush(), send a query to query space every time and update it to db at the end of the transaction
When you do save(), it finally creates query from object existing in persistence context and updates it to db at the end of transaction.
That's why I recommend use save() instead of saveAndFlush() for effective utilization

Note: The insert statement is updated to the unconditional query space



Bye!