はまる!!jpa #glassfish_jp #javaee

Post on 10-May-2015

3.212 Views

Category:

Technology

0 Downloads

Preview:

Click to see full reader

TRANSCRIPT

はまる! J PA

@ M A K I N G 槙 俊明

2 0 1 3 - 1 2 - 1 3 G L A S S F I S H U S E R S G R O U P J A PA N 勉強会 2 0 1 3 # 2

自己紹介

• @making

• 大手SIerでR&D

• JJUG幹事

• 金魚本(http://amzn.to/JavaEE6)を一部翻訳

[宣伝 ] はじめてのB O O T S T R A P出版 !

• #はじboo

• http://bit.ly/hajiboo

• プレゼント用に1冊持ってきました!

みなさん J PAつかっていますか?

私の J PA経験

• とある企業のバックエンドシステム

• 約 50エンティティ、約 80 k LOC

• X億ユーザー・・・

• おれおれBlogシステム

• https://github.com/making/categolj2-backend

• 約 10エンティティ、now developing

僕が J PAを使って遭遇した

はまりポイントをだらだら述べていきます

動作確認環境

• GlassFish: 4

• JPA API: 2.1

• JPA Provider: Eclipse Link 2.5.0

• RDBMS: MySQL 5.1 (古い・・)

動作確認環境

• GlassFish: 4

• JPA API: 2.1

• JPA Provider: Eclipse Link 2.5.0

• RDBMS: MySQL 5.1 (古い・・)

はまったときは J PA 2 . 0

+ H I B E R N AT E 4

よくある注文履歴画面

O R D E R O R D E R _ I T E M I T E M

1…N M…1

E N T I T Yクラス

E N T I T Yクラス

N:1

E N T I T Yクラス

N:1

M : 1

一覧表示処理 E J B

FA C E L E T S

データ投入

• 注文件数: 100件

• 注文1件あたり5品注文

実行!

・・・

・・・遅い

間題に気づいた人いますか?

ログを確認

persistence.xmlに以下のプロパティを設定する

ログを確認…

ログを確認…

O R D E Rを検索して

ログを確認…

O R D E Rを検索して

O R D E R毎に O R D E R _ I T E Mを検索して

ログを確認…

O R D E Rを検索して

O R D E R毎に O R D E R _ I T E Mを検索して

O R D E R _ I T E M毎に I T E Mを検索

ログを確認…

O R D E Rを検索して

O R D E R毎に O R D E R _ I T E Mを検索して

O R D E R _ I T E M毎に I T E Mを検索

1 + 1 0 0 X ( 1 + 5 ) = 6 0 1回 S Q Lが実行されている・・・

はまりポイント 1 :

N + 1問題

F E T C H _ T Y P E = L A Z Yなので この段階では関連E N T I T YはF E T C Hされていない

F E T C H _ T Y P E = L A Z Yなので この段階では関連E N T I T YはF E T C Hされていない

関連E N T I T YにアクセスしたタイミングでS Q L発行

F E T C H _ T Y P E = L A Z Yなので この段階では関連E N T I T YはF E T C Hされていない

関連E N T I T YにアクセスしたタイミングでS Q L発行

関連E N T I T YにアクセスしたタイミングでS Q L発行

E J Bを修正

E J Bを修正

J O I N F E T C Hで 予めまとめてF E T C H

再実行!

速く・・・

速く・・・ない

ログを確認…

ログを確認…

O R D E RとO R D E R _ I T E Mは まとめて取得できているが

ログを確認…

O R D E RとO R D E R _ I T E Mは まとめて取得できているが

O R D E R _ I T E M毎に I T E Mを検索・・・

ログを確認…

O R D E RとO R D E R _ I T E Mは まとめて取得できているが

O R D E R _ I T E M毎に I T E Mを検索・・・1 + 5 0 0 = 5 0 1回

S Q Lが実行されている・・・

E J Bを確認

E J Bを確認

ここが効いていない

J PA仕様では・・・

• ネストしたJOIN FETCHはサポートされていない

• JOIN FETCHのエイリアスを設定できない

J PA仕様では・・・

• ネストしたJOIN FETCHはサポートされていない

• JOIN FETCHのエイリアスを設定できない

H I B E R N AT Eではサポートされている

E C L I P S E L I N Kでの対応方法

ヒントを追加

再実行!

速く・・・

速く・・・なった!

ログを確認

ログを確認

1回にまとまった!

教科書レベルのはまりポイントでした

補足

• 別解:NEW式を使う

• http://d.hatena.ne.jp/megascus/20120925/1348575449 参考

• EclipseLinkではデフォルトでキャッシュが効くため、2回目以降は速い・・・

• pesistence.xmlに以下を設定してキャッシュを無効にして検証

次いきましょう

とあるA C C O U N T更新画面

とあるA C C O U N T更新画面

A C C O U N T全件表示

とあるA C C O U N T更新画面

A C C O U N T全件表示

ボタンを押すと E M A I Lを更新

A C C O U T更新ロジック

• 入力されたEmailが既に別のユーザーが使用していた場合は例外スロー

• それ以外の場合はAccountを更新

更新してみる

更新してみる

使用されていないE M A I L

更新してみる

使用されていないE M A I L

更新してみる

使用されていないE M A I L

更新してみる

使用されていないE M A I L

ファッ!?

E J Bの実装を確認

間違いに気づいた人いますか?

ログを確認

ログを確認

ログを確認C O U N Tの前に

U P D AT Eが発行されている!?

はまりポイント 2 :

更新されちゃってた問題

E J Bの実装を確認

E J Bの実装を確認

E J Bの実装を確認F I N Dで取得したA C C O U N Tは

E N T I T Y M A N A G E R管理下

E J Bの実装を確認F I N Dで取得したA C C O U N Tは

E N T I T Y M A N A G E R管理下

E J Bの実装を確認F I N Dで取得したA C C O U N Tは

E N T I T Y M A N A G E R管理下

E N T I T Y M A N A G E R管理下 のエンティティを更新

E J Bの実装を確認F I N Dで取得したA C C O U N Tは

E N T I T Y M A N A G E R管理下

E N T I T Y M A N A G E R管理下 のエンティティを更新

E J Bの実装を確認F I N Dで取得したA C C O U N Tは

E N T I T Y M A N A G E R管理下

E N T I T Y M A N A G E R管理下 のエンティティを更新

クエリを実行する前に いったんエンティティを

D Bに反映させる

E J Bの実装を確認F I N Dで取得したA C C O U N Tは

E N T I T Y M A N A G E R管理下

E N T I T Y M A N A G E R管理下 のエンティティを更新

クエリを実行する前に いったんエンティティを

D Bに反映させる

E J Bの実装を確認F I N Dで取得したA C C O U N Tは

E N T I T Y M A N A G E R管理下

E N T I T Y M A N A G E R管理下 のエンティティを更新

クエリを実行する前に いったんエンティティを

D Bに反映させる

C O U N T = 1 になる

E J Bの実装を確認F I N Dで取得したA C C O U N Tは

E N T I T Y M A N A G E R管理下

E N T I T Y M A N A G E R管理下 のエンティティを更新

クエリを実行する前に いったんエンティティを

D Bに反映させる

C O U N T = 1 になる

E J Bの実装を確認F I N Dで取得したA C C O U N Tは

E N T I T Y M A N A G E R管理下

E N T I T Y M A N A G E R管理下 のエンティティを更新

クエリを実行する前に いったんエンティティを

D Bに反映させる

C O U N T = 1 になる

M E R G EはE N T I T Y M A N A G E R管理下から はずれたエンティティを管理下に戻す処理

E J Bの実装を確認F I N Dで取得したA C C O U N Tは

E N T I T Y M A N A G E R管理下

E N T I T Y M A N A G E R管理下 のエンティティを更新

クエリを実行する前に いったんエンティティを

D Bに反映させる

C O U N T = 1 になる

M E R G EはE N T I T Y M A N A G E R管理下から はずれたエンティティを管理下に戻す処理ここでは不要

E N T I T Yのライフサイクル

���

��������

������� ��

�������

���� ���

���������������

���������������

��������

��� ��

����������

E N T I T Yのライフサイクル

���

��������

������� ��

�������

���� ���

���������������

���������������

��������

��� ��

����������

ここのタイミングに注意! F L U S H、 J P Q L、・・・

E J Bを修正

E J Bを修正

E J Bを修正

最後に更新

E J Bを修正

最後に更新

コミットのタイミング (メソッド正常終了時 )で エンティティをD Bに反映させる

思った通りの結果に

次いきましょう

1対多 + 複合キーなケース

E J B

E J B

C A S C A D E _ T Y P E = A L L なので関連E N T I T Yもまとめて登録できる

テストデータ登録

テストデータ登録

C A S C A D E = A L L なのでN U L Lでいいはず・・

エラーで起動しない・・・

エラーで起動しない・・・

間違いに気づいた人いますか?

(これはちょっと難しい )

どっちに

書き込めばいいか

わからない

はまりポイント 3 :

どこで親 I Dを設定すればいいかわからない問題

苦肉の策

苦肉の策

コメントアウトして 単方向の関連に・・・

再実行

再実行

S Q Lが発行されたが、A R T I C L E _ I Dが設定されない・・

E J Bを修正

E J Bを修正

TA G以外をいったん保存

E J Bを修正

TA G以外をいったん保存

F L U S Hして I Dを採番

E J Bを修正

TA G以外をいったん保存

F L U S Hして I Dを採番

採番した I Dを設定して保存

動いた・・・!

これでいいのか!?

これでいいのか!?

• CASCADE_TYPE=ALLなのに関連エンティティを1つずつ保存している

• EJB実装のアドホック感・・・

• 双方向の関連ではエラーになる

これでいいのか!?

• CASCADE_TYPE=ALLなのに関連エンティティを1つずつ保存している

• EJB実装のアドホック感・・・

• 双方向の関連ではエラーになる

根本解決を!

調べたらあった!

E N T I T Y修正

複合キーの対応フィールド名を指定する

E J B (再 )

E J B (再 )

C A S C A D E _ T Y P E = A L L なので関連E N T I T Yもまとめて登録できる

うまく動いた!

(実は )ここまでの話は・・・

もともとH I B E R N AT Eではまっていた問題

• 余計なものまで更新されちゃう問題

• 削除したつもりが削除されていなかった問題

• StackOverflow問題

もともとH I B E R N AT Eではまっていた問題

• 余計なものまで更新されちゃう問題

• 削除したつもりが削除されていなかった問題

• StackOverflow問題

E C L I P S E L I N K版で調査間に合わず!

次回

はまる! J PA PA R T 2

へ続く・・・

重要なこと

• JPAを使う場合は、必ずSQLログを出力しよう。

• Entityのライフサイクルを把握しておこう。

• 根本解決を心がけよう。結果オーライな対処を続けていると「JPAこわい」で終わる

次回に続く ( ? )

top related