67335


下記に示すように参考資料を読みましたが、わかりませんでした。  
なぜ **わからない** のか関係しそうなところを引用します。

[java - Difference between save and saveAndFlush in Spring data jpa - Stack
Overflow](https://stackoverflow.com/questions/21203875/difference-between-
save-and-saveandflush-in-spring-data-jpa)

> but, in my project, I use save(), saveAll() & it persists in DB without
> commit or flush calling explicitly. Then why should I prefer saveAndFlush?
> FLush mode all those things are in default mode

（私のプロジェクトではコミットとフラッシュなしに使っている）

[Difference Between save() and saveAndFlush() in Spring Data JPA |
Baeldung](https://www.baeldung.com/spring-data-jpa-save-saveandflush)

> As the name depicts, the save() method allows us to save an entity to the
> DB. It belongs to the CrudRepository interface defined by Spring Data. Let's
> see how we can use it:
>
> employeeRepository.save(new Employee(1L, "John"));
>
> Normally, Hibernate holds the persistable state in memory. The process of
> synchronizing this state to the underlying DB is called flushing.

（Hibernateはメモリに保持している。DBに保存するのをフラッシュと呼ぶ。）

[Spring Data Jpa Save and SaveAndFlush - Stack
Overflow](https://stackoverflow.com/questions/48162222/spring-data-jpa-save-
and-saveandflush)

> saveAndFlush() additionally calls EntityManager.flush() that will execute
> all retained SQL statements.

（保存されているSQL文すべて実行する）

# わからないことまとめ

  * 私のプロジェクトでも`save`しか使っておりません。そしてDBにデータが反映されることを確認しています。`saveAndFlash`を使うことは必要なのでしょうか？
  * リポジトリーの実装によって挙動が変わってきそうな内容ですね。私はHibernateを使っています。英語の記事だとメモリにデータがあるのでフラッシュしないとDB反映されなさそうですが、私の環境では `save` のみでDB反映されています。なぜでしょうか？
  * `EntityManager.flush()`はすべてのSQLを実行するとありますが、私は`save`のみしか使っていないので「すべて」がどういうことで何を示すのかわかりません。具体的な例がありましたら知りたいです。


CC BY-SA 4.0
2020-06-05T03:16:25.110
67308
2020-06-05T13:57:49.313
9008
question
java database spring kotlin spring-boot
saveとsaveAndFlushの違いがわかりません


Hibernateにおいて、`save`と`flush`は次のようなニュアンスです。

  * `save`: ユーザが生成したエンティティをHibernate管理下に置く(=永続化対象にする)
  * `flush`: Hibernateが管理している状態をDBに書き出し、管理している状態とDBが保持する情報を同期させる。要は実際にSQLを実行する。

ユーザが参照するのHibernateが管理している状態であり、DBの状態は原則的には気にする必要がありません。  
なので`flush`を使う機会がない、というのは普通です。  
ユーザが明示的に`flush`を行わずとも、必要に応じて(例: トランザクションcommit時に)Hibernateは管理している状態をDBに反映させます。

Hibernateのリファレンスの次の章が該当します:

  * [5\. Persistence Context](https://docs.jboss.org/hibernate/orm/5.3/userguide/html_single/Hibernate_User_Guide.html#pc)
    * エンティの状態を transient から managed にするメソッドがHibernateの`save`です([Spring Data JPAの`save`](https://github.com/spring-projects/spring-data-jpa/blob/2.3.0.RELEASE/src/main/java/org/springframework/data/jpa/repository/support/SimpleJpaRepository.java#L551-L559)は[`merge`](https://docs.jboss.org/hibernate/orm/5.3/userguide/html_single/Hibernate_User_Guide.html#pc-merge)も一緒くたになっていますが)
  * [6\. Flushing](https://docs.jboss.org/hibernate/orm/5.3/userguide/html_single/Hibernate_User_Guide.html#flushing)

* * *

>   *
> 私のプロジェクトでもsaveしか使っておりません。そしてDBにデータが反映されることを確認しています。saveAndFlashを使うことは必要なのでしょうか？
>

パフォーマンス低下防止を目的として、一度に多量のSQLを実行せずに済むように`flush`を挟む、みたいな用途が最も有り得そうかなと思います。

また、ユーザがDBへの反映タイミングを制御したい場合にも必要になるかもしれません。  
例えばトラクション分離レベルが関わってくる話だとDBのデータを更新したのかどうかは気にする必要があるでしょう。

私の経験としては、監査記録としてDBのSQLログを用いるため特定のタイミングではSQL文を必ず実行したい、という要求を実現するため`flush`を用いていたようなものもありました。

>   *
> リポジトリーの実装によって挙動が変わってきそうな内容ですね。私はHibernateを使っています。英語の記事だとメモリにデータがあるのでフラッシュしないとDB反映されなさそうですが、私の環境では
> save のみでDB反映されています。なぜでしょうか？
>

`flush`を行うとそのタイミングでSQLが実行されますが、`flush`を行わずともいずれはSQLが実行されます。  
なので、フラッシュしないとDB反映されない、というのはそのタイミングではそうかもしれませんが、長期的(例えばトランザクション終了後)まで考えると正しくありません。いずれは反映されます。

>   *
> EntityManager.flush()はすべてのSQLを実行するとありますが、私はsaveのみしか使っていないので「すべて」がどういうことで何を示すのかわかりません。具体的な例がありましたら知りたいです。
>

例えば次のようなコードの場合、`saveAndFlush`を`save`に変えると、`INERT`も`UPDATE`も実行されません(※[Flusing
mode:
`AUTO`](https://docs.jboss.org/hibernate/orm/5.3/userguide/html_single/Hibernate_User_Guide.html#flushing-
auto)の場合):

[code]

        @Transactional
        public String method() {
    
            final MyEntity e = new MyEntity();
            final MyEntity p = repository.saveAndFlush(e);
            p.setName("renamed");
            repository.saveAndFlush(p);
    
            throw new RuntimeException(); // rollback
        }
    
[/code]

* * *

(以下、根拠のない私の想像ですが)  
`saveAndFlush`というメソッドは、おそらく、「`save`メソッドを呼んだらSQLが実行されれてDBが更新されると思ったのにされないんですけど…！？」というSpring
Data JPAユーザの頻出疑問に応えるためのお節介メソッドです。  
なので、`save`で事足りているのであれば`saveAndFlush`については存在を気にする必要は無いと思います。

そもそも、`save`は引数で指定した特定のエンティティをターゲットにするのに対し、`flush`はHibernate管理エンティティ全てがターゲットなので、いつでも`saveAndFlush`として一緒くたにまとめてしまって良いわけでも無いです。


CC BY-SA 4.0
2020-06-05T13:57:49.313
67335
2020-06-05T13:57:49.313
2808
67308
answer