Lock in $30 Savings on PRO—Offer Ends Soon! ⏳

2023/4/27 Java仕様勉強会: Jakarta Persistence

2023/4/27 Java仕様勉強会: Jakarta Persistence

2023/4/27 Java仕様勉強会で使用したスライドです。

spec
https://jakarta.ee/specifications/persistence/3.1/

Eclipse Starter for Jakarta EE
https://start.jakarta.ee/

The Jakarta® EE Tutorial
https://eclipse-ee4j.github.io/jakartaee-tutorial/

Satoshi Seto

April 27, 2023
Tweet

More Decks by Satoshi Seto

Other Decks in Technology

Transcript

  1. 2 ▸ 名前:瀬戸 智 ▸ Twitter: @megascus ▸ ServletとかJPAあたりが好きで、一時期個人でServletとJPAのJavaDocを翻訳していた。 ・

    そのあとPleiadesの人が機械翻訳をしてくれるようになったので現時点では意味なし。 自己紹介
  2. 4 ▸ Jakarta EE サーバーが実装しているリレーショナルデータベースアクセスの仕様 ▸ Java SEでも使用可能 ▸ データアクセスとともにObject-Relational

    Mappingも行う ▸ 現在の最新版はJakarta Persistence 3.1 (Jakarta EE 10) ▸ 昔はJava Persistence API(JPA)という名前だった ▸ この資料ではJakarta Persistence だと長いのでJPAと呼びます! Jakarta Persistenceとは
  3. 9 ▸ SQLを直接使う場合に比べてデータベース の差異を隠してくれるため、プログラムの 可搬性に優れる ▸ JDBCに比べてボイラープレートを削減す ることができ、実装の効率が良くなる ▸ キャッシュ等の仕様が組み込まれており、

    性能面で利点がある ▸ 可搬性を考えるとSQLを直接使う場合に比 べて使用できる機能が減る ▸ JDBCよりも暗黙の動作が多いため、初心 者に理解しにくい ▸ キャッシュ等の仕様があるためJPA以外と の併用が難しい JPAを使うメリット・デメリット メリット デメリット
  4. 10 ※一部ライブラリは最新版の仕様に準拠していない場合があります。 JPAを実装したライブラリ ▸ Hibernate ▸ EclipseLink ▸ OpenJPA ▸

    DataNucleus ▸ その他 Jakarta EE Server ▸ WildFly ▸ Open Liberty ▸ Eclipse GlassFish ▸ Payara Community ▸ Apache TomEE ▸ その他 JPAの仕様と実装 JPAはただの仕様なので、実際に使用するときは実装が必要
  5. 18 ▸ Persistence Contextが日本語に翻訳された時に表記ゆれが発生している ・ 永続化コンテキスト ・ 永続性コンテキスト ・ 永続コンテキスト

    ・ 持続性コンテキスト ※製品によってはドキュメント内でブレている場合もあり。 この資料ではPersistenceから始まるものは永続化~で統一しています。 (補足)永続化コンテキストの表記ゆれ
  6. 21 すべてのJakarta EEサーバーで共通で以下のような感じ(実装依存を含む) ▸ JDBCドライバーをサーバーに登録 ▸ DBコネクションをデータソースとしてコネクションプールに登録 ▸ war内の/WEB-INF/classes/META-INF/persistence.xmlに永続化ユニットを定義 ・

    永続化ユニットは永続化コンテキストに問い合わせるためのAPI ▸ 定義した永続化ユニットをCDI を使用して取得 ・ 取得できるクラス(インターフェース)はjakarta.persistence.EntityManager JPAを使い始めるまでの設定
  7. 22 ※Jakarta EEサーバー以外も含めるとTomcatが1位 ▸ 2022年のJakarta EE Serveyで一番使われていたJakarta EEサーバー(※) ・ https://www.wildfly.org/

    ▸ WildFly Quickstarts (作り始める時のベースとしても便利) ・ https://docs.wildfly.org/27/Quickstarts.html ※一部wildfly固有の設定が含まれているため 他のAPサーバーでは動かないことがあります。 WildFly(実装依存部分の説明に使用)
  8. 31 ▸ @jakarta.persistence.Entityアノテーションを付けたJava Beansクラス(※)を準備する。 ▸ このクラスはエンティティと呼ばる。 ▸ このエンティティのインスタンスが データベースの内容と同期化される。 ※Java

    Beansはいわゆるアクセサ(getter/setter)のついた、パラメーターをメンバー変数として持ち、デフォルトコンス トラクタのあるクラス エンティティの準備
  9. 36 エンティティに関わる永続化コンテキストを操作するメソッド 説明 メソッド 新しいエンティティを永続化コンテキストにエンティティを紐づける persist() (新しい、もしくは一度紐づけが解除された)エンティティを永続化コンテキストに紐づける merge() 永続化コンテキストからデータを取得する(データベースからデータを取得する) find()

    エンティティと永続化コンテキストとの紐づけを解除する、このエンティティへの変更はデータ ベースと同期がとられなくなる detach() 永続化コンテキストにデータを削除するように指示する remove() 永続化コンテキストとデータベースの内容を同期する(=SQLを発行してデータベースを更新 する) flush() エンティティの内容をデータベースの内容で更新する refresh() 永続化コンテキストの内容をクリアし、永続化コンテキストに紐づいているエンティティすべて の紐づけを解除する clear()
  10. 37 ▸ トランザクション境界の外側にいったエンティティは自動的に永続化コンテキストの紐づ けから解除される ▸ Jakarta EEサーバーではデフォルトでCDI 管理beanの内部はトランザクション境界内とな る ▸

    トランザクション境界は設定で変更できるので、挙動がおかしいと感じたらトランザクシ ョン境界内かを確認する必要がある。 ・ 特に大規模プロジェクトでは基盤チームが設定変更していることが多い・・・・ (補足)トランザクションの内側と外側を分けるトランザクション境界
  11. 40 ▸ @jakarta.persistence.Entityアノテーションを付けたJava Beansクラス ▸ このエンティティのインスタンスがデータベースの内容と同期化される ▸ エンティティの1インスタンスがテーブルの1行に相当する エンティティ Employeeクラス

    EMPLOYEEテーブル String employeeId CHAR(8) EMPLOYEE_ID String firstName VARCHAR(100) FIRST_NAME String lastName VARCHAR(100) LAST_NAME Date hireDate DATE HIRE_DATE String jobCode CHAR(8) JOB_CODE long salary DECIMAL(12,0) SALARY
  12. 42 ※継承関係がある場合にクラスの属性をテーブルにどうマッピングするのかの指定 @Entity @Inheritance(strategy=JOINED) public class Customer { ... }

    @Entity public class ValuedCustomer extends Customer { ... } 共通フィールドを一つのテーブルにまとめてサブクラス固有のフィールド用のテーブルを別途作るか、 クラスごとにテーブルを作成するか、すべての属性を一つのテーブルにまとめるか、の三択。 検索時の性能に影響する。 エンティティ/テーブルのマッピングで使用するアノテーション例 説明 アノテーション エンティティをマッピングするテーブルの名前や、テーブルが持つユニーク制約を指定する @Table 複数のテーブルを一つのエンティティにマッピングしたい場合にして @SecondaryTable @SecondaryTableを複数個使いたい場合に使用 @SecondaryTables サブクラスをどうやってテーブルにマッピングするかを指定する(※) @Inheritance @Entity @Inheritance(strategy=JOINED) public class Customer { ... } @Entity public class ValuedCustomer extends Customer { ... }
  13. 43 フィールド/カラムのマッピングで使用するアノテーション例 説明 アノテーション マッピングするカラムの名前や長さ、null許容等の情報を入力する。JPAのエンティティから テーブルを生成する場合の情報としても使用する。 @Column プライマリーキーに指定する。エンティティに必須。※あとで説明 @Id, @EmbededId

    Enumをデータベースに保存したい時に序数で保存するか文字列で保存するか指定する。 @Enumerated フィールドとデータベースのカラムの型変換を行うクラスを指定する。※あとで説明 @Convert Blob/Clobをマッピングするときに指定。 @Lob 日付型をマッピングするときに指定。 @Temporal 楽観ロックに使用する。※後で説明 @Version フィールドをデータベースにマッピングしないことを指定する。(デフォルトでマッピングされる) @Transient ※これらのアノテーションはフィールドもしくはgetterに適用できます。
  14. 54 JPAではJakarta Persistence Query Language(JPQL)とCriteria APIの2種類のクエリーを独自 サポートしている ▸ JPQLはエンティティを対象としたSQLライクなクエリー言語で、SQLを使用したことが ある人なら直感的に利用できる

    ▸ Criteria APIはStream APIのようにJavaのオブジェクト・メソッドをくみ上げることでクエ リーを構築することができ、型安全にクエリーが作れるのが特徴 ※両方で同じことができます。 JPA用の2種類のクエリー言語 こちらのみを説明
  15. 56 ▸ Select句 例) select e from Employee e where

    e.id = :id ▸ Update句 例) update Employee e set e.salary = e.salary * 1.01 ▸ Delete句 例) delete Employee e where e.salary > 10000 JPQLの種類
  16. 57 select e from Employee e where e.id = :id

    JPQLの書き方の基本 SQLではテーブルに対してクエリーを書く / JPAではエンティティに対してクエリーを書く 検索対象とするエンティティのクラス名(もしくは @Entityのnameで指定した値) JPAではバインド引数に名前を指定できる。 もしくは”?1”のように序数でも指定が出来る。 (JDBC:SQLの?の代わり) SQLでのカラムの代わりにJPAではエンティティを返す
  17. 58 select e.department from Employee e where e.id = :id

    JPQLの書き方-リレーションシップでの取得 SQLではテーブルに対してクエリーを書く / JPAではエンティティに対してクエリーを書く エンティティのリレーションシップを利用して 他のエンティティを返すこともできる ※departmentはEmployeeエンティティから@ManyToOneで紐づいている
  18. 59 select e from Employee e where e.department.id = :id

    JPQLの書き方-リレーションシップでの検索 SQLではテーブルに対してクエリーを書く / JPAではエンティティに対してクエリーを書く エンティティのリレーションシップを利用して 他のエンティティの条件で検索する
  19. 60 select e.name from Employee e where e.id = :id

    JPQLの書き方-エンティティ以外を返す SQLではテーブルに対してクエリーを書く / JPAではエンティティに対してクエリーを書く 従業員名のStringが返る
  20. 62 select e from Employee e where e.salary > all

    ( select m.salary from Manager m where m.department = e.department) JPQLの書き方-サブクエリー 相関サブクエリーも使えます all、any、someのいずれか
  21. 63 select e from Employee e where type(e) in (Exempt,

    Contractor) JPQLの書き方-特定の型のエンティティの検索 ポリモーフィズムを利用している場合 Employeeのなかで サブクラスExemptもしくはContractorに含まれるものすべて
  22. 64 select p from Person p where 'Joe’ member of

    p.nicknames JPQLの書き方-コレクションに含まれている場合 Collectionに含まれるものの検索 Personは複数のnicknameを持ち その中に’Joe’が含まれているものを返す
  23. 65 select new dev.megascus.CustomerDetail(c.id, c.name, c.department.name) from Customer c JPQLの書き方-コンストラクタ式

    コンストラクタに引数を渡す形でJavaオブジェクトを直接生成できる
  24. 66 ABS, ALL, AND, ANY, AS, ASC, AVG, BETWEEN, BIT_LENGTH,

    BOTH, BY, CASE, CEILING, CHAR_LENGTH, CHARACTER_LENGTH, CLASS, COALESCE, CONCAT, COUNT, CURRENT_DATE, CURRENT_TIME, CURRENT_TIMESTAMP, DELETE, DESC, DISTINCT, ELSE, EMPTY, END, ENTRY, ESCAPE, EXISTS, EXP, EXTRACT, FALSE, FETCH, FLOOR, FROM, FUNCTION, GROUP, HAVING, IN, INDEX, INNER, IS, JOIN, KEY, LEADING, LEFT, LENGTH, LIKE, LOCAL, LN, LOCATE, LOWER, MAX, MEMBER, MIN, MOD, NEW, NOT, NULL, NULLIF, OBJECT, OF, ON, OR, ORDER, OUTER, POSITION, POWER, ROUND, SELECT, SET, SIGN, SIZE, SOME, SQRT, SUBSTRING, SUM, THEN, TRAILING, TREAT, TRIM, TRUE, TYPE, UNKNOWN, UPDATE, UPPER, VALUE, WHEN, WHERE ※そのほかSQLで使うキーワードは将来予約語になる可能性があるため使用は推奨されない JPQLの予約語(=使える機能)
  25. 68 EntityManagerのメソッドから実行できる ▸ Selectの例 em.createQuery(“SELECT c FROM Customer c WHERE

    c.name LIKE :custName”) .setParameter(“custName”, “Scott”) // custNameに”Scott”をバインド .setMaxResults(10) // 結果を10件に絞る .getResultList(); // 結果をListとして取得 ※結果を1件のみ取得するメソッドも存在する ※update、deleteはJDBCと同じように別のメソッドが準備されている JPQLの実行方法
  26. linkedin.com/company/red-hat youtube.com/user/RedHatVideos facebook.com/redhatinc twitter.com/RedHat 76 Red Hat is the world’s

    leading provider of enterprise open source software solutions. Award- winning support, training, and consulting services make Red Hat a trusted adviser to the Fortune 500. Thank you