ビールとプリンとプログラミング。

頭の悪いプログラマのぼやき。

はじめてのJPAでちょっと怖い勘違い

はい。タイトル通りです。

JPAに触れ始めて3年近く経ちます。

どうも、私です。




昔、私も勘違いしていたこと。そして、つい先日もプロジェクト内であった間違い。

検証気力がないのでメモ程度に。






JPAとは

Java Persistence APIJPA)とは、関係データベースのデータを扱う Java SE および Java EE のアプリケーションを開発するためのJavaフレームワークである。

だそうです。(Java Persistence API - Wikipediaより)



要するにデータベース周りを扱うフレームワークですね。



詳しい扱い方は今回取り扱いません。

今回は初心者の勘違いポイントだけ。




JPAでは、プログラマが意識的にINSERT文やUPDATE文の指示を行いません。
SQL文を発行する内容やタイミングは、EntityManagerがコントロールします。

EntityManagerはEntityを管理します。
そして、EntityManagerの管理下にあるオブジェクトは、最終的にDBと同期されます。

プログラマはEntityManagerを使用して、Entityの状態を操作します。



Entityの状態を操作する、下記のメソッド達が、時に勘違いポイントになることがあるので気を付けましょう。
というのが、今回のお話です。

  • persist(Object entity)
  • merge(T entity)
  • remove(Object entity)



では、1つずつ、勘違いしてきましょう。

persist

persistはnewしたオブジェクトをEntityManagerの管理下に新規追加します。


ふむふむ、persistするとINSERTするんだなあ。

違います



persistはINSERTを流すためのメソッドではありません。
あくまで、EntityManagerの管理下に、新たなEntityを追加するメソッドです。
結果的にコミットまでにはINSERT文が発行されるにすぎません。

いつ発行するかをこちらが意識することは通常ないのです。

merge

mergeは(管理下から外れた)オブジェクトをEntityManagerの管理下に戻します。


ふむふむ、mergeするとUPDAt違います



通常EntityManagerを通してDBから取得したオブジェクトはEntityManagerの管理下にあります。ですので、管理下から外れない限り、mergeは不要です。
イメージからはpersistで追加されるので、mergeで変更だろうと思いがちですし、
実際にそのように説明される場合もあるかと思います。

ですが、あくまでもmergeは管理下に置くだけであり、UPDATE文を発行するわけではありません。
(勿論、結果的にコミットまでにはUPDATE文が発行される場合はあります。)

逆に言うと、mergeを行わずとも、EntityManagerの管理下にあるオブジェクトに対して、値の変更を行った場合は、UPDATE文が発行される場合があります。


この辺が勘違いしやすく、また危険なところです。



「mergeしてないはずなのにDBが変更されてしまっていた!!!」



という事がありえるのです。




では、いつ管理下から外れるか。
それは意図的にdetachメソッドを使用した場合や、トランザクションから抜けたタイミング(コミットされたタイミング)等です。

remove

removeは、管理下のオブジェクトに対して、削除予約を行います。
これも、結果的にコミットまでにDELETE文が発行されますが、DELETE文を発行するメソッドではありません。




管理下??

JPAの使い方をサラッと学んで、実際に手を動かして、メソッドと結果を見ると、INSERTやUPDATEの命令を行っているんだ。と勘違いすることがあります。
ですが、最初にも書いた通り、JPAでは自動的にエンティティとDBが同期されます。我々が操作するのは、あくまでもエンティティの状態と、エンティティが持つ値です。

上記メソッドの意味を理解するには、まずエンティティの状態について知る必要があります。
少し昔の記事のようですが、下の記事は図があって、理解の助けになりました。

d.hatena.ne.jp



そんなわけで、
実際にありえた、JPAのちょっと怖い勘違い。

これから始める人は、ぜひお気を付けください。








基本的な使い方はJavaEE7と合わせてこちらも。

enterprisegeeks.hatenablog.com










以上、yusuke_s24でした。