はまる!!JPA #glassfish_jp #javaee

6,811 views

Published on

Published in: Technology
0 Comments
28 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total views
6,811
On SlideShare
0
From Embeds
0
Number of Embeds
862
Actions
Shares
0
Downloads
63
Comments
0
Likes
28
Embeds 0
No embeds

No notes for slide

はまる!!JPA #glassfish_jp #javaee

  1. 1. @MAKING 槙 俊明 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 は ま る ! J PA
  2. 2. 自己紹介 • @making • 大手SIerでR&D • JJUG幹事 • 金魚本(http://amzn.to/JavaEE6)を一部翻訳
  3. 3. [宣伝] はじめてのBOOTSTRAP出版! • #はじboo • http://bit.ly/hajiboo • プレゼント用に1冊持ってきました!
  4. 4. み な さ ん J PA つ か っ て い ま す か ?
  5. 5. 私 の J PA 経 験 • とある企業のバックエンドシステム • 約 50エンティティ、約 80 k LOC • X億ユーザー・・・ • おれおれBlogシステム • https://github.com/making/categolj2-backend • 約 10エンティティ、now developing
  6. 6. 僕 が J PA を 使 っ て 遭 遇 し た はまりポイントをだらだら述べていきます
  7. 7. 動作確認環境 • GlassFish: 4 • JPA API: 2.1 • JPA Provider: Eclipse Link 2.5.0 • RDBMS: MySQL 5.1 (古い・・)
  8. 8. 動作確認環境 はまったときは • 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
  9. 9. よくある注文履歴画面 1…N ORDER M…1 ORDER_ITEM ITEM
  10. 10. E N T I T Y ク ラス
  11. 11. N :1 E N T I T Y ク ラス
  12. 12. N :1 E N T I T Y ク ラス M:1
  13. 13. 一覧表示処理 EJB FA C E L E T S
  14. 14. データ投入 • 注文件数: 100件 • 注文1件あたり5品注文
  15. 15. 実行!
  16. 16. ・・・
  17. 17. ・・・遅い
  18. 18. 間題に気づいた人いますか?
  19. 19. ログを確認 persistence.xmlに以下のプロパティを設定する
  20. 20. … ログを確認
  21. 21. … ログを確認 O R D E R を 検 索 して
  22. 22. ログを確認 O R D E R を 検 索 して ORDER毎に … O R D E R _ I T E M を 検 索 して
  23. 23. ログを確認 O R D E R を 検 索 して ORDER毎に O R D E R _ I T E M を 検 索 して ORDER_ITEM毎に … ITEMを検索
  24. 24. ログを確認 O R D E R を 検 索 して ORDER毎に O R D E R _ I T E M を 検 索 して ORDER_ITEM毎に ITEMを検索 … 1 + 100 X (1 + 5) = 601回 S Q L が 実 行 さ れて い る ・ ・ ・
  25. 25. はまりポイント1: N+1問題
  26. 26. FETCH_TYPE=LAZYなので こ の 段 階 で は 関 連 E N T I T Y は F E T C H さ れて い な い
  27. 27. FETCH_TYPE=LAZYなので こ の 段 階 で は 関 連 E N T I T Y は F E T C H さ れて い な い 関 連 E N T I T Y に アク セ ス し たタイミングでSQL発行
  28. 28. FETCH_TYPE=LAZYなので こ の 段 階 で は 関 連 E N T I T Y は F E T C H さ れて い な い 関 連 E N T I T Y に アク セ ス し たタイミングでSQL発行 関 連 E N T I T Y に アク セ ス し たタイミングでSQL発行
  29. 29. EJBを修正
  30. 30. EJBを修正 JOIN FETCHで 予めまとめてFETCH
  31. 31. 再実行!
  32. 32. 速く・・・
  33. 33. 速く・・・ない
  34. 34. … ログを確認
  35. 35. ログを確認 ORDERとORDER_ITEMは … まとめて取得できているが
  36. 36. ログを確認 ORDERとORDER_ITEMは … まとめて取得できているが ORDER_ITEM毎に ITEMを検索・・・
  37. 37. ログを確認 ORDERとORDER_ITEMは … まとめて取得できているが ORDER_ITEM毎に 1 + 500 = 501回 S Q L が 実 行 さ れて い る ・ ・ ・ ITEMを検索・・・
  38. 38. EJBを確認
  39. 39. EJBを確認 ここが効いていない
  40. 40. J PA 仕 様 で は ・ ・ ・ • ネストしたJOIN FETCHはサポートされていない • JOIN FETCHのエイリアスを設定できない
  41. 41. J PA 仕 様 で は ・ ・ ・ • ネストしたJOIN FETCHはサポートされていない • JOIN FETCHのエイリアスを設定できない H I B E R N AT E で は サ ポ ー ト さ れ て い る
  42. 42. ECLIPSELINKでの対応方法 ヒントを追加
  43. 43. 再実行!
  44. 44. 速く・・・
  45. 45. 速く・・・なった!
  46. 46. ログを確認
  47. 47. ログを確認 1回にまとまった!
  48. 48. 教科書レベルのはまりポイント でした
  49. 49. 補足 • 別解:NEW式を使う • http://d.hatena.ne.jp/megascus/20120925/1348575449 参考 • EclipseLinkではデフォルトでキャッシュが効くため、2 回目以降は速い・・・ • pesistence.xmlに以下を設定してキャッシュを無効に して検証
  50. 50. 次いきましょう
  51. 51. とあるACCOUNT更新画面
  52. 52. とあるACCOUNT更新画面 ACCOUNT全件表示
  53. 53. とあるACCOUNT更新画面 ACCOUNT全件表示 ボ タ ン を 押 すと EMAILを更新
  54. 54. ACCOUT更新ロジック • 入力されたEmailが既に別のユーザーが使用していた 場合は例外スロー • それ以外の場合はAccountを更新
  55. 55. 更 新 して み る
  56. 56. 更 新 して み る 使 用 さ れて い な い E M A I L
  57. 57. 更 新 して み る 使 用 さ れて い な い E M A I L
  58. 58. 更 新 して み る 使 用 さ れて い な い E M A I L
  59. 59. 更 新 して み る 使 用 さ れて い な い E M A I L ファッ!?
  60. 60. EJBの実装を確認
  61. 61. 間違いに気づいた人いますか?
  62. 62. ログを確認
  63. 63. ログを確認
  64. 64. ログを確認 COUNTの前に U P D AT E が 発 行 さ れ て い る ! ?
  65. 65. はまりポイント2: 更新されちゃってた問題
  66. 66. EJBの実装を確認
  67. 67. EJBの実装を確認
  68. 68. EJBの実装を確認 FINDで取得したACCOUNTは ENTITYMANAGER管理下
  69. 69. EJBの実装を確認 FINDで取得したACCOUNTは ENTITYMANAGER管理下
  70. 70. EJBの実装を確認 FINDで取得したACCOUNTは ENTITYMANAGER管理下 ENTITYMANAGER管理下 のエンティティを更新
  71. 71. EJBの実装を確認 FINDで取得したACCOUNTは ENTITYMANAGER管理下 ENTITYMANAGER管理下 のエンティティを更新
  72. 72. EJBの実装を確認 FINDで取得したACCOUNTは ENTITYMANAGER管理下 ENTITYMANAGER管理下 のエンティティを更新 クエリを実行する前に いったんエンティティを DBに反映させる
  73. 73. EJBの実装を確認 FINDで取得したACCOUNTは ENTITYMANAGER管理下 ENTITYMANAGER管理下 のエンティティを更新 クエリを実行する前に いったんエンティティを DBに反映させる
  74. 74. EJBの実装を確認 FINDで取得したACCOUNTは ENTITYMANAGER管理下 ENTITYMANAGER管理下 のエンティティを更新 COUNT=1 になる クエリを実行する前に いったんエンティティを DBに反映させる
  75. 75. EJBの実装を確認 FINDで取得したACCOUNTは ENTITYMANAGER管理下 ENTITYMANAGER管理下 のエンティティを更新 COUNT=1 になる クエリを実行する前に いったんエンティティを DBに反映させる
  76. 76. EJBの実装を確認 FINDで取得したACCOUNTは ENTITYMANAGER管理下 ENTITYMANAGER管理下 のエンティティを更新 COUNT=1 になる クエリを実行する前に いったんエンティティを DBに反映させる MERGEはENTITYMANAGER管理下から はずれたエンティティを管理下に戻す処理
  77. 77. EJBの実装を確認 FINDで取得したACCOUNTは ENTITYMANAGER管理下 ENTITYMANAGER管理下 のエンティティを更新 COUNT=1 になる クエリを実行する前に いったんエンティティを DBに反映させる ここでは不要 MERGEはENTITYMANAGER管理下から はずれたエンティティを管理下に戻す処理
  78. 78. E N T I T Y の ラ イ フ サ イク ル
  79. 79. E N T I T Y の ラ イ フ サ イク ル ここのタイミングに注意! FLUSH、JPQL、・・・
  80. 80. EJBを修正
  81. 81. EJBを修正
  82. 82. EJBを修正 最後に更新
  83. 83. EJBを修正 最後に更新 コミットのタイミング(メソッド正常終了時)で エンティティをDBに反映させる
  84. 84. 思った通りの結果に
  85. 85. 次いきましょう
  86. 86. 1 対 多 + 複 合 キ ー な ケ ース
  87. 87. EJB
  88. 88. EJB CASCADE_TYPE=ALL なので関連ENTITYもまとめて登録できる
  89. 89. テス ト デ ー タ 登 録
  90. 90. テス ト デ ー タ 登 録 CASCADE=ALL なのでNULLでいいはず・・
  91. 91. エラーで起動しない・・・
  92. 92. エラーで起動しない・・・
  93. 93. 間違いに気づいた人いますか? (これはちょっと難しい)
  94. 94. どっちに 書き込めばいいか わからない
  95. 95. はまりポイント3: どこで親IDを設定すればいいかわからない問題
  96. 96. 苦肉の策
  97. 97. 苦肉の策 コ メ ン トア ウ ト して 単方向の関連に・・・
  98. 98. 再実行
  99. 99. 再実行 SQLが発行されたが、ARTICLE_IDが設定されない・・
  100. 100. EJBを修正
  101. 101. EJBを修正 TA G 以 外 を い っ た ん 保 存
  102. 102. EJBを修正 TA G 以 外 を い っ た ん 保 存 F L U S H して I D を 採 番
  103. 103. EJBを修正 TA G 以 外 を い っ た ん 保 存 F L U S H して I D を 採 番 採 番 し た I D を 設 定 して 保 存
  104. 104. 動いた・・・!
  105. 105. こ れで い い の か ! ?
  106. 106. こ れで い い の か ! ? • CASCADE_TYPE=ALLなのに関連エンティティを1つず つ保存している • EJB実装のアドホック感・・・ • 双方向の関連ではエラーになる
  107. 107. こ れで い い の か ! ? • CASCADE_TYPE=ALLなのに関連エンティティを1つず つ保存している • EJB実装のアドホック感・・・ • 双方向の関連ではエラーになる 根本解決を!
  108. 108. 調べたらあった!
  109. 109. ENTITY修正 複合キーの対応フィールド名 を指定する
  110. 110. EJB(再)
  111. 111. EJB(再) CASCADE_TYPE=ALL なので関連ENTITYもまとめて登録できる
  112. 112. うまく動いた!
  113. 113. (実は)ここまでの話は・・・
  114. 114. も と も と H I B E R N AT E で は ま っ て い た 問 題 • 余計なものまで更新されちゃう問題 • 削除したつもりが削除されていなかった問題 • StackOverflow問題
  115. 115. も と も と H I B E R N AT E で は ま っ て い た 問 題 • 余計なものまで更新されちゃう問題 • 削除したつもりが削除されていなかった問題 • StackOverflow問題 ECLIPSELINK版で調査間に合わず!
  116. 116. 次回 は ま る ! J PA PA R T 2 へ続く・・・
  117. 117. 重要なこと • JPAを使う場合は、必ずSQLログを出力しよう。 • Entityのライフサイクルを把握しておこう。 • 根本解決を心がけよう。結果オーライな対処を続けて いると「JPAこわい」で終わる
  118. 118. 次回に続く(?)

×