Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.
App Engine for Java の JDO
使用上の考慮点

   (株)ケーピーエス 平 克介
目次
   RDB から JDO への実装の変更概要
       今回トライした例について
   JDO の基本
   考慮点 –  Transaction
   考慮点 – 関連
   考慮点 –  PersistenceMan...
KPS フレームワークの機能
    クライアントから直接擬似 HibernateAPI を操作
        ORM オブジェクトを検索、更新、作成、削除
    クライアントからサーバー側 Sesar2 コンポーネン
     トの...
JDO への移行
   サーバー側の ORM アクセス部分の変更
       Hibernate から JDO へ
           フレームワーク側の変更
   クライアント側検索 API の変更
       Criteri...
JDO の基本1
   JDO とは
       Java 標準のデータの永続化・検索機能を提供す
        る API
   JDO の ORM クラス( GAE では kind と呼
    ぶ)
    @Persisten...
JDO の基本 2

   Object(entity) を永続化する


       PersistenceManager pm = PMF.get().getPersistenceManager();
       Employee e...
JDO の基本 3
   Object の更新
     PersistenceManager pm = PMF.get().getPersistenceManager();
     try {
         Employee e = ...
JDO の基本 4
   Object の検索
    Query query = pm.newQuery(Employee.class);
    query.setFilter("lastName == lastNameParam");
...
JDO の基本 5
    Transaction
    Transaction tx = pm.currentTransaction();
    try {
        tx.begin();
        ClubMembers...
JDO の基本 6
   com.google.appengine.api.datastore.Key
    import com.google.appengine.api.datastore.Key;
    // ...
       ...
JDO の基本 7
   関連
       Employee.java
    // ...
        @Persistent(mappedBy = "employee")
        private List<ContactI...
参考資料
   ORM クラス間の一般的な関連の実装方法
                       RDB の場合:主キー / 外部キーの関連
     商品テーブル
                                   ...
考慮点 (Transaction)
   1 Transaction 内では同一の entity group に
    属する entity しか扱えない
           tx.begin();
         Query quer...
考慮点 (Transaction)
   Transaction の制約を受けない方法
       単一の entity 「 root 」をすべての親の無い entity
        の親にする


                 ...
考慮点 (Transaction)
   Root クラス ( 主キーだけあればよい )
    @PersistenceCapable(identityType = IdentityType.APPLICATION)
    public ...
考慮点 (Transaction)
   親の無い entity の例( Root の Key を持たせる )
 @PersistenceCapable(identityType = IdentityType.APPLICATION)
pub...
考慮点 (Transaction)
   親が root である Entity の新規作成
       root の key をセットする (root のキー値が1の場
        合)
    // ...
    Employee...
考慮点 ( 関連 )
    関連実装時の問題(関連が Key の構造にな
     る)
         親を一度設定すると変更できない
         複数の親を定義できない
  division1          divisi...
考慮点 7 ( 関連 - 解決策 )
     関連は親の Key を保持することで実装する
@PersistenceCapable(identityType = IdentityType.APPLICATION)
public class ...
考慮点 (PersistenceManager)
   PersistenceManager の使いまわし
       一連の処理で使用する PersistenceManager は同
        一のものを使用する必要がある。
  ...
考慮点 (PersistenceManager)
   PersistenceManager を request に保持する
      public class PMManager {
      public static final S...
考慮点 (PersistenceManager)
   PMManager から入手する例

     // ...
      Season s = question.getSeason();
      s.setCnt(s.getCnt...
考慮点 (Index)
   検索条件によっては明示的に Index を定義す
    る必要がある。
       Google の資料で Index 定義が必要な検索とは
           複数のソートが指定された場合
     ...
考慮点 (Index)
   Index の設定例
       war/WEB-INF/datastore-indexes.xml に指定

        <?xml version="1.0" encoding="utf-8"?>
 ...
その他の考慮点

   kind 間の Join による読み込みはできない
   group by を使用した集約関数は使用できない
       count(*) / sum(xxx) 等
   検索条件に  != 、 IN は使用で...
おわり

   ありがとうございました
Upcoming SlideShare
Loading in …5
×

Gaej Jdo

3,212 views

Published on

Published in: Technology
  • Be the first to comment

Gaej Jdo

  1. 1. App Engine for Java の JDO 使用上の考慮点 (株)ケーピーエス 平 克介
  2. 2. 目次  RDB から JDO への実装の変更概要  今回トライした例について  JDO の基本  考慮点 –  Transaction  考慮点 – 関連  考慮点 –  PersistenceManager  考慮点 –  Index  参考:基本情報技術者試験 午前問題特訓システム
  3. 3. KPS フレームワークの機能  クライアントから直接擬似 HibernateAPI を操作  ORM オブジェクトを検索、更新、作成、削除  クライアントからサーバー側 Sesar2 コンポーネン トの呼び出し  Gxt   GUI 画面デザインツール  D-RexGxt Hibernate 部分を JDO へ入れ替え Criteria を Query 集計処理部分の  へ変更 変更
  4. 4. JDO への移行  サーバー側の ORM アクセス部分の変更  Hibernate から JDO へ  フレームワーク側の変更  クライアント側検索 API の変更  Criteria から Query へ  フレームワークおよびクライアントコードの変更  集計処理部分の変更  集計処理を行っている Seaser2 コンポーネントの 変更
  5. 5. JDO の基本1  JDO とは  Java 標準のデータの永続化・検索機能を提供す る API  JDO の ORM クラス( GAE では kind と呼 ぶ) @PersistenceCapable(identityType = IdentityType.APPLICATION) public class Employee { @PrimaryKey @Persistent(valueStrategy = IdGeneratorStrategy.IDENTITY) private Long id; @Persistent private String firstName; @Persistent private String lastName; この下に constructor : getter/setter が続く
  6. 6. JDO の基本 2  Object(entity) を永続化する PersistenceManager pm = PMF.get().getPersistenceManager(); Employee e = new Employee("Alfred", "Smith", new Date()); try { pm.makePersistent(e); } finally { pm.close(); } :
  7. 7. JDO の基本 3  Object の更新 PersistenceManager pm = PMF.get().getPersistenceManager(); try { Employee e = pm.getObjectById(Employee.class, 1); e.setTitle(newTitle); } finally { pm.close(); } :  Object の削除 pm.deletePersistent(e);        :
  8. 8. JDO の基本 4  Object の検索 Query query = pm.newQuery(Employee.class); query.setFilter("lastName == lastNameParam"); query.setOrdering("hireDate desc"); query.declareParameters("String lastNameParam"); try { List<Employee> results = (List<Employee>) query.execute("Smith"); if (results.iterator().hasNext()) { for (Employee e : results) { // ... } } else { // ... no results ... Where lastName=‘Smith’ } Order by hireDate desc } finally { に相当 query.closeAll(); } :
  9. 9. JDO の基本 5  Transaction Transaction tx = pm.currentTransaction(); try { tx.begin(); ClubMembers members = pm.getObjectById(ClubMembers.class, "k12345"); members.incrementCounterBy(1); pm.makePersistent(members); tx.commit(); } finally { if (tx.isActive()) { Tx 間に他所で同じ entity が更新された場 tx.rollback(); 合 } JDOOptimisticVerificationException とな } る :
  10. 10. JDO の基本 6  com.google.appengine.api.datastore.Key import com.google.appengine.api.datastore.Key; // ... @PrimaryKey @Persistent(valueStrategy = IdGeneratorStrategy.IDENTITY) private Key key; public void setKey(Key key) { this.key = key; } :  親のクラスを持つ場合は主キーに Key を使用する  Key は親のクラスの Key への参照を持つ  子 Key→ 親 Key  Entity の Key は変更できない
  11. 11. JDO の基本 7  関連  Employee.java // ... @Persistent(mappedBy = "employee") private List<ContactInfo> contactInfoSets;  ContactInfo.java // ... @Persistent private Employee employee;  Employee:Contactinfo = 1:N  この場合 Employee が Contactinfo の親になる  共通の親(親の親も含む)を持つ entity の集合を entity group と言う
  12. 12. 参考資料  ORM クラス間の一般的な関連の実装方法 RDB の場合:主キー / 外部キーの関連 商品テーブル 外部キ 商品 CD 商品名 単価 商品メーカー CDー 商品メーカーテーブル 商品メーカー CD 商品メーカー名 関連相手の Object 主キー の参照を持つ 関連相手の Object の集合の参照を持つ ORM でのオブジェクト間の関連 Shohin ShohinMaker 1 String shohinCd 0..* String shohinMakerCd String shohinNm String shohinMakerNm Long tanka Set shohins ShohinMaker shohinMaker getShohinMaker() getShohins()
  13. 13. 考慮点 (Transaction)  1 Transaction 内では同一の entity group に 属する entity しか扱えない    tx.begin(); Query query = pm.newQuery(Employee.class); List<Employee> results = (List<Employee>) query.execute(); Employee e1 = results.get(0); Employee e2 = results.get(1); e1.setFirstName(e1.getFirstName() + "1"); e2.setFirstName(e2.getFirstName() + "2"); tx.commit(); javax.jdo.JDOException  つまり、共通の親を持つ entity しか Transaction 化できない
  14. 14. 考慮点 (Transaction)  Transaction の制約を受けない方法  単一の entity 「 root 」をすべての親の無い entity の親にする root employee1 employee2 employee3 company1 company2 contactInfo1 contactInfo2 すべては同一の entity group
  15. 15. 考慮点 (Transaction)  Root クラス ( 主キーだけあればよい ) @PersistenceCapable(identityType = IdentityType.APPLICATION) public class Root { @PrimaryKey @Persistent(valueStrategy = IdGeneratorStrategy.IDENTITY) private Key key; public Key getKey() { return key; } public void setKey(Key key) { this.key = key; } }
  16. 16. 考慮点 (Transaction)  親の無い entity の例( Root の Key を持たせる ) @PersistenceCapable(identityType = IdentityType.APPLICATION) public class Employee { @PrimaryKey @Persistent(valueStrategy = IdGeneratorStrategy.IDENTITY) private Key key; @Persistent @Extension(vendorName="datanucleus", key="gae.parent-pk", value="true") private Key rootKey; public void setRootKey(Key rootKey) { this.rootKey = rootKey; } }  Root との ManyToOne 関連を持たせる方法でも OK
  17. 17. 考慮点 (Transaction)  親が root である Entity の新規作成  root の key をセットする (root のキー値が1の場 合) // ... Employee e = new Employee("Alfred", "Smith", new Date()); Key key = KeyFactory.createKey("Root", 1); e.setRootKey(key); pm.makePersistent(e); :
  18. 18. 考慮点 ( 関連 )  関連実装時の問題(関連が Key の構造にな る)  親を一度設定すると変更できない  複数の親を定義できない division1 division2 2009 年春の「コンピュータの基礎」の問題 season1 genre1 x employee1 x Employee1 は一生 division1 question1 Season と Genre 両方親に出来ない
  19. 19. 考慮点 7 ( 関連 - 解決策 )  関連は親の Key を保持することで実装する @PersistenceCapable(identityType = IdentityType.APPLICATION) public class Question { @PrimaryKey @Persistent(valueStrategy = IdGeneratorStrategy.IDENTITY) private Key key; @Persistent private Key seasonKey; @Persistent 関連先 Object を要求された時 private Key genreKey; に entity を読む public Season getSeason() { if (this.seasonKey == null) { return null; } return getPm().getObjectById(Season.class, this.seasonKey); } public void setSeason(Season season) { this.seasonKey = season.getKey(); } :
  20. 20. 考慮点 (PersistenceManager)  PersistenceManager の使いまわし  一連の処理で使用する PersistenceManager は同 一のものを使用する必要がある。 // ... Season s = question.getSeason(); s.setCnt(s.getCnt()+1); pm.makePersistent(s); public Season getSeason() { if (this.seasonKey == null) { return null; } return pm.getObjectById(Season.class, this.seasonKey); }
  21. 21. 考慮点 (PersistenceManager)  PersistenceManager を request に保持する public class PMManager { public static final String pmName = " PMManager _PM"; public static PersistenceManager getPm() { HttpServletRequest request = null; PersistenceManager pm = null; try { request = (HttpServletRequest) SingletonS2ContainerFactory .getContainer().getComponent(HttpServletRequest.class); pm = (PersistenceManager) request.getAttribute(pmName); } catch (Exception e) { } if (pm == null) { pm = PMF.get().getPersistenceManager(); if (request != null) { request.setAttribute(pmName, pm); この場合 Seasar2 のコンテナ } から request を得ている } return pm; } }
  22. 22. 考慮点 (PersistenceManager)  PMManager から入手する例 // ... Season s = question.getSeason(); s.setCnt(s.getCnt()+1); PMManager.getPm().makePersistent(s); public Season getSeason() { if (this.seasonKey == null) { return null; } return PMManager.getPm() . getObjectById(Season.class, this.seasonKey); }
  23. 23. 考慮点 (Index)  検索条件によっては明示的に Index を定義す る必要がある。  Google の資料で Index 定義が必要な検索とは  複数のソートが指定された場合  Key の逆順ソートの場合  == でない条件と == の条件がある場合  == の条件と ancestor フィルターがある場合  Local 環境で OK でも Deploy した環境で NG の場 合がある
  24. 24. 考慮点 (Index)  Index の設定例  war/WEB-INF/datastore-indexes.xml に指定 <?xml version="1.0" encoding="utf-8"?> <datastore-indexes autoGenerate="false"> <datastore-index kind="Question" ancestor="false" source="auto"> <property name="seasonKey" direction="asc"/> <property name="genreKey" direction="asc"/> </datastore-index> </datastore-indexes>
  25. 25. その他の考慮点  kind 間の Join による読み込みはできない  group by を使用した集約関数は使用できない  count(*) / sum(xxx) 等  検索条件に  != 、 IN は使用できない  Python ではクライアント側の実装として実現し ている  検索条件の組み合わせで or 、 not は使用で きない
  26. 26. おわり  ありがとうございました

×