ラベル データストア の投稿を表示しています。 すべての投稿を表示
ラベル データストア の投稿を表示しています。 すべての投稿を表示

2011年10月7日金曜日

Google Cloud SQLがプレビューに

Google App Engineでデータを保存・取り出しを行うには、
Datastoreを利用する必要があります。

APIとしては、
・JPA
・JDO
・低レベルAPI
を利用します。

JPAやJDOを利用すると、App Engineのインスタンスがスピンアップするたびに
長い待ち時間が発生するという欠点があり、
低レベルAPIは既存のSQLとは全く違います。

そこで、新たにGoogle Cloud SQLというAPIが登場して、
JDBC(Java向け)、DB-API(Python向け)によってアクセスできる
データベースのインターフェイスを提供するようです。

Google Codeブログでの紹介はこちら

インストール不要・無料のKaede翻訳ツール:
http://kaedetrans.appspot.com/

2011年10月3日月曜日

Google App Engine for Java の非同期データストアAPIの呼び出し(その6)

Google App Engineのデータストアは、
非同期に呼び出して結果を取得することも出来ます。

英語版ドキュメントはこちら
その1,その2,その3,その4,その5も参照してみてください。


When To Use Async Datastore Calls 非同期データストア呼び出しの使用タイミング

DatastoreServiceインターフェイスによって提示される操作は同期呼び出しをします。例えば、コードは、DatastoreService.get()を呼び出すした時にデータストアへのコールが完了するまでブロックします。アプリケーションが行う必要のある1つだけの動作がHTML内でget()の結果をレンダリングすることの場合、呼び出しが完了するまでブロックすることは完全に合理的なことです。
しかしながら、アプリケーションがget()の結果にプラスしてクエリの結果をレスポンスにレンダリングする場合、またはget()とクエリがデータ依存関係を持たない場合、get()が完了するまで待ってからクエリを開始するのは時間の無駄です。ここでは、非同期APIを用いて改善されたコードの例を示します。

DatastoreService datastore = DatastoreServiceFactory.getDatastoreService();
Key empKey = KeyFactory.createKey("Employee", "Max");

// Read employee data from the Datastore
Entity employee = datastore.get(empKey); // Blocking for no good reason!

// Fetch payment history
Query query = new Query("PaymentHistory");
PreparedQuery pq = datastore.prepare(query);
List<Entity> result = pq.asList(FetchOptions.Builder.withLimit(10));
renderHtml(employee, result);

get()が完了するまで待つかわりに、非同期にメソッド呼び出しを実行するためにAsyncDatastoreServiceのインスタンスを使用します。

AsyncDatastoreService datastore = DatastoreServiceFactory.getAsyncDatastoreService();
Key empKey = KeyFactory.createKey("Employee", "Max");

// Read employee data from the Datastore
Future<Entity> employeeFuture = datastore.get(empKey); // Returns immediately!

// Fetch payment history for the employee
Query query = new Query("PaymentHistory", empKey);
PreparedQuery pq = datastore.prepare(query);

// Run the query while the employee is being fetched
List<Entity> result = pq.asList(FetchOptions.Builder.withLimit(10));
// Implicitly performs query asynchronously
Entity employee = employeeFuture.get(); // Blocking!
renderHtml(employee, result); 

このコードの同期バージョンと非同期バージョンは、同様な量のCPUを使用します(結局のところ、どちらも同じ計算量を示します)が、非同期バージョンは平行動作のために2つのデータストア操作を行うので、非同期バージョンの方が待ち時間がより少なくなります。一般的に、データ依存関係のない複数のデータストア操作を行う必要がある場合は、AsyncDatastoreServiceは大幅に待ち時間を改善します。

インストール不要・無料のKaede翻訳ツール:
http://kaedetrans.appspot.com/

2011年10月2日日曜日

Google App Engine for Java の非同期データストアAPIの呼び出し(その5)

Google App Engineのデータストアは、
非同期に呼び出して結果を取得することも出来ます。

英語版ドキュメントはこちら
その1,その2,その3,その4も参照してみてください。



Async Queries (非同期クエリ)

現時点では、明示的にクエリ向けの非同期APIを提示してはいません。しかしながら、PreparedQuery.asIterable(),PreparedQuery.asIterator(),PreparedQuery.asList(FetchOptions fetchOptions)メソッドを呼び出すと、DatastoreServiceまたはAsyncDatastoreServiceのどちらも、直ちに値を返し、非同期に結果を先取りします。これによってアプリケーションの動作がクエリの結果が取得される間に平行して行われます。

// ...

Query q1 = new Query("Salesperson");
q1.addFilter("dateOfHire", FilterOperator.LESS_THAN, oneMonthAgo);

// Returns instantly, query is executing in the background.
Iterable recentHires = datastore.prepare(q1).asIterable();

Query q2 = new Query("Customer");
q2.addFilter("lastContact", FilterOperator.GREATER_THAN, oneYearAgo);

// Also returns instantly, query is executing in the background.
Iterable needsFollowup = datastore.prepare(q2).asIterable();

schedulePhoneCall(recentHires, needsFollowUp);



インストール不要・無料のKaede翻訳ツール:
http://kaedetrans.appspot.com/

2011年9月30日金曜日

Google App Engine for Java の非同期データストアAPIの呼び出し(その4)

Google App Engineのデータストアは、
非同期に呼び出して結果を取得することも出来ます。

英語版ドキュメントはこちら
その1,その2,その3も参照してみてください。

Working with Futures (Futureの使用)

Future のJavadocは、非同期データストアAPIから返されたFutureを上手く使用する上で知る必要のあることのほとんどを説明していますが、App Engine固有の注意点があります。
Future.get(long timeout, TimeUnit unit)メソッドを呼び出した時に、timeoutはAsyncDatastoreServiceを生成した時点のRPCデッドラインのセットから切り離されています。詳しくは、datastore RPC deadlinesのドキュメントを参照してください。
Future.cancel(boolean mayInterruptIfRunning)メソッドを呼び出し、trueが返された場合、データストアの状態が変更されていないことを必ずしも意味するものではありません。言い換えると、Futureをキャンセルすることは、トランザクションをロールバックすることと同じではありません。

インストール不要・無料のKaede翻訳ツール:
http://kaedetrans.appspot.com/

2011年9月26日月曜日

Google App Engine for Java の非同期データストアAPIの呼び出し(その3)

Google App Engineのデータストアは、
非同期に呼び出して結果を取得することも出来ます。

英語版ドキュメントはこちら
その1はこちら,その2はこちら


Workind with Async Transactions 非同期トランザクションの使用

非同期データストアAPI呼び出しは、同期呼び出しと同じようにトランザクションに参加することができます。ここで挙げるのは、従業員の給料の額を調整し、Employeeと同じエンティティグループにSalaryAdjustmentエンティティを1つのトランザクション内で追加して書き込みます。

void giveRaise(AsyncDatastoreService datastore, Key employeeKey, long raiseAmount)
        throws Exception {
    Future txn = datastore.beginTransaction();

    // Async call to lookup the Employee entity
    Future employeeEntityFuture = datastore.get(employeeKey);

    // Create and put a SalaryAdjustment entity in parallel with the lookup
    Entity adjustmentEntity = new Entity("SalaryAdjustment", employeeKey);
    adjustmentEntity.setProperty("adjustment", raiseAmount);
    adjustmentEntity.setProperty("adjustmentDate", new Date());
    datastore.put(adjustmentEntity);

    // Fetch the result of our lookup to make the salary adjustment
    Entity employeeEntity = employeeEntityFuture.get();
    long salary = (Long) employeeEntity.getProperty("salary");
    employeeEntity.setProperty("salary", salary + raiseAmount);

    // Re-put the Employee entity with the adjusted salary.
    datastore.put(employeeEntity);
    txn.commit(); // could also call txn.commitAsync() here
}

このサンプルは、トランザクション無しの非同期呼び出しとトランザクション内での非同期呼び出しの違いを示しています。トランザクションを利用していない場合、独立した非同期呼び出しの官僚を確認する唯一の方法は、呼び出しが行われた時に戻されたFutureの値を取得するということになります。トランザクションを利用すると、Transaction.commit()の呼び出しが、トランザクション開始からコミットされる前までの全ての非同期呼び出しの結果をブロックします。

そのため、上記の例では、SalaryAdjustmentエンティティの挿入を行う非同期呼び出しがtxn.commit()を呼び出された時点では未解決の可能性があるにもかかわらず、挿入が完了するまでにコミットは起こりません。同様に、txn.commit()の代りにtxn.commitAsync()の呼び出しを選択すると、commitAsync()から返されたFutureのget()メソッド呼び出しが全ての未解決の非同期呼び出しが干渉するまでブロックします。

ノート:トランザクションは特定のスレッドに関連付けられますが、DatastoreServiceやAsyncDfatastoreServiceの特定のインスタンスには関連付けられません。これの意味するところは、あるDatastoreServiceからトランザクションを開始して、
あるAsyncDatastoreServiceから非同期呼び出しを行うと、非同期呼び出しはトランザクションに参加する、ということです。または、もっと簡潔に言えば、
DatastoreService.getCurrentTransaction()とAsyncDatastoreService.getCurrentTransaction()は常に同じトランザクションを返すということです。

インストール不要・無料のKaede翻訳ツール:
http://kaedetrans.appspot.com/

2011年9月25日日曜日

Google App Engine for Java の非同期データストアAPIの呼び出し(その2)

Google App Engineのデータストアは、
非同期に呼び出して結果を取得することも出来ます。

英語版ドキュメントはこちら
その1はこちら

Working with the Async Datastore Service (非同期データストアサービスの使用)

非同期データストアAPIでは、AsyncDatastoreServiceインターフェイスのメソッドを使ってデータストア呼び出しを行います。このオブジェクトはDatastoreServiceFactoryクラスのgetAsyncDatastoreService()クラスメソッドを呼び出して
取得します。

import com.google.appengine.api.datastore.AsyncDatastoreService;
import com.google.appengine.api.datastore.DatastoreServiceFactory;

// ...
AsyncDatastoreService datastore = DatastoreServiceFactory.getAsyncDatastoreService();

AsyncDatastoreServiceは、結果の取得を後の時点でブロックすることが出来るFutureを直ちに返すメソッドを除いて、DatastoreServiceと同じ操作をサポートしています。例として、DatastoreService.get()は1つのエンティティを返しますが、AsyncDataStoreService.get()はFuture<Entity>を返します。

// ...

Key key = KeyFactory.createKey("Employee", "Max");
// Async call returns immediately
Future<entity> entityFuture = datastore.get(key);

// Do other stuff while the get operation runs in the background...

// Blocks if the get operation has not finished, otherwise returns instantly
Entity entity = entityFuture.get();

ノート:get()メソッドを呼び出すまでは例外はスローされません。このメソッドの呼び出しは非同期操作の成功/不成功の検査に利用できます。

AsyncDatastoreServiceを取得しているけれども同期した操作の実行を必要とする場合、適切なAsyncDatastoreServiceのメソッドを呼び出してからすぐにresultのブロックをかけます。

// ...

Entity entity = new Employee("Employee", "Alfred");
// ... populate entity properties

// Make a sync call via the async interface
Key key = datastore.put(key).get();

インストール不要・無料のKaede翻訳ツール:
http://kaedetrans.appspot.com/

2011年9月22日木曜日

Google App Engine for Java の非同期データストア呼び出し

Google App Engineのデータストアは、
非同期に呼び出して結果を取得することも出来ます。

英語版ドキュメントはこちら


Async Datastore API (非同期データストアAPI)

非同期データストアAPIは、リクエストのハンドリングよりも後の時点で、並列にブロッキングされないデータストア呼び出しから結果を取得することを可能にします。このドキュメントは非同期データストア呼び出しの以下の側面を記述しています。
・Working with the Async Datastore Service 非同期データストアサービスの動作
・Working with Async Transactions 非同期トランザクションの動作
・Working with Futures Futureの動作
・Async Queries 非同期クエリ
・When To Use Async Datastore Calls 非同期データストア呼び出しの使用タイミング


インストール不要・無料のKaede翻訳ツール:
http://kaedetrans.appspot.com/

2011年9月19日月曜日

Google App Engine のHigh Replication Datastoreの利用(その5)

前回まででGoogle App Engine の
High Replication Datastoreの使用についてのドキュメントを翻訳しました。
(原文はこちら)

データストアには2種類あり、
・High Replication Datastore
・Master/Slave Datastore
です。

GAEのデータストアは、データを複数のデータストアに
保存しますが、データストアへのアクセスの仕方に違いがあります。

マスター/スレーブデータストアは、
プログラムからアクセスされるデータストアは1つで
保存・読み出しをする先は複数になります。
マスターデータストアに障害が発生すると、
データストアの読み書きが出来なくなるという欠点があります。

High Replication Datastore(HRD)は、
アクセスするデータストアを1つに限定しないので
可用性が上がります。有料版は99.95%の保障をしています。
(これまでのところ、実運用上で99.99%以上のようです)
しかし、書き込みを開始してから全体の更新が完了する
までに読み出しが行われると、
読み出されたデータが最新のものであるとは限りません。
そのため、アプリケーションの性質によっては
レスポンスに最新の更新が反映されるような工夫が必要となる、
ということのようです(それが、前回の内容)。

マスター/スレーブを使用すればいい…のですが、
今後廃止となる予定だそうです。

インストール不要・無料のKaede翻訳ツール:
http://kaedetrans.appspot.com/

2011年9月15日木曜日

Google App Engine for Java のHigh Replication Datastoreの使用(その4)

Google App Engine for Javaのデータストアには2種類あり、
そのうちの1つを選択して使用します。

9月9日の記事から、2種類のデータストアのうちの
High Replication Datastore(高レプリケーションデータストア、HRD)の
使用方法についてのドキュメントの翻訳です。

原文はこちらです。
前回の翻訳はこちら

使用上の注意

上記の高レプリケーションデータストアのサンプルコードは1つのゲストブックあたりに単一のエンティティグループとなるように書かれています。これは単一のゲストブック上のクエリには強い一貫性を与えますが、1秒当たり1回の書き込み(エンティティグループへのサポートの制限)を行うようにゲストブックを制限するようになります。従って、1つのゲストブックあたりに単一のエンティティグループに書き込みを行うのは高い頻度での利用が
見込まれる場合には最適ではありません。アプリケーションが高い書き込み要求に遭遇する可能性が高い場合、別の手段を使用することを検証してください。例として、最近の投稿を有効期限付きでmemcacheにputして、その後、データストアから取得した投稿とmemcacheからの最近の投稿を合わせた結果を表示する方法があります。
最終的な一貫性として、数秒内に実行されるクエリに対しては書き込みの99.9%以上に対して利用できます。アプリケーションに投稿するのにかかる時間の間に、現在のユーザーへデータを提供するための解決方法を見つけることが目標となります。解決方法として、memcacheを使用したり、クッキーに保存したり、URLに状態を付け加えたり、その他全く別の方法があるかもしれません。ポイントは、投稿のコンテキストにある現在のユーザーにデータを提供する方法が、高レプリケーションデータストアが完全に許容する最終的な一貫性を作り出すために十分となるようにすることです。get(),put()やトランザクションを行うと、常に直前に書き込まれたデータを参照するということを忘れないで下さい。

インストール不要・無料のKaede翻訳ツール:
http://kaedetrans.appspot.com/

2011年9月12日月曜日

Google App Engine for Java のHigh Replication Datastoreの使用(その3)

Google App Engine for Javaのデータストアには2種類あり、
そのうちの1つを選択して使用します。

前々回から、2種類のデータストアのうちの
High Replication Datastore(高レプリケーションデータストア、HRD)の
使用方法についてのドキュメントの翻訳です。

原文はこちらです。
前回の翻訳はこちら


In the High Replication Datastore (高レプリケーションデータストア)

高レプリケーションデータストアでは、サンプルのゲストブックアプリケーションはキー名guestbookNameと共にGuestbookカインドの親キーを使い、その後のあいさつ文を親キーによって判別されるエンティティグループ内に保存します。
String guestbookName = req.getParameter("guestbookName");
        Key guestbookKey = KeyFactory.createKey("Guestbook", guestbookName);
        String content = req.getParameter("content");
        Date date = new Date();
        // Places the greeting in the same entity group as the guestbook
        Entity greeting = new Entity("Greeting", guestbookKey);
        greeting.setProperty("user", user);
        greeting.setProperty("date", date);
        greeting.setProperty("content", content);
あいさつ文用クエリは、特定のguestbookに追加された挨拶のみを見つける祖先クエリを実行するために親であるGuestbookキーを使います。:
DatastoreService datastore = DatastoreServiceFactory.getDatastoreService();
    Key guestbookKey = KeyFactory.createKey("Guestbook", guestbookName);
    Query query = new Query("Greeting", guestbookKey).addSort("date", Query.SortDirection.DESCENDING);
    query.setAncestor(guestbookKey);
    List<Entity> greetings = datastore.prepare(query).asList(FetchOptions.Builder.withLimit(10));

インストール不要・無料のKaede翻訳ツール:
http://kaedetrans.appspot.com/

2011年9月10日土曜日

Google App Engine for Java の High Replication Datastoreの使用(その2)

Google App Engine for Javaのデータストアには2種類あり、
そのうちの1つを選択して使用します。

前回から、2種類のデータストアのうちの
High Replication Datastore(高レプリケーションデータストア、HRD)の
使用方法についてのドキュメントの翻訳です。

原文はこちらです。
前回の翻訳はこちら

In the Master/Slave Datastore (マスター/スレーブデータストア)

マスター/スレーブデータストアでは、それぞれの挨拶に対して新しいルートエンティティを生成します(/google/apphosting/demos/guestbook/src/guestbook/で利用できます)。
Entity greeting = new Entity("Greeting");
// No parent key specified, so the Entity is a root.
greeting.setProperty("user", user);
greeting.setProperty("date", date);
greeting.setProperty("content", content);
10個の最新の挨拶を取得するクエリ:
DatastoreService datastore = DatastoreServiceFactory.getDatastoreService();
Query query = new Query("Greeting").addSort("date", Query.SortDirection.DESCENDING);
List<entity> greetings = datastore.prepare(query).asList(FetchOptions.Builder.withLimit(10));
マスター/スレーブデータストアは全てのクエリに対して強い一貫性を持つ結果を提供するため、このスキーマはうまく機能します。デフォルトではデータストアの読み書きを1つのマスターレプリカからのみ行うため、マスター/スレーブデータストアは強い一貫性を持つ結果を提供します。
このクエリを高レプリケーションデータストアで試すと、クエリを実行するために使用されるデータセンターはクエリ実行時に新しいあいさつ文を見つけられないかも知れません。

インストール不要・無料のKaede翻訳ツール:
http://kaedetrans.appspot.com/

2011年9月9日金曜日

Google App Engine for JavaのHigh Replication Datastoreの使用

前回までの翻訳で述べられている通り、
Google App Engine for Javaのデータストアには2種類あり、
そのうちの1つを選択して使用します。

今回から、2種類のデータストアのうちの
High Replication Datastore(高レプリケーションデータストア、HRD)の
使用方法についてのドキュメントの翻訳です。

原文はこちらです。

Using the High Replication Datastore (高レプリケーションデータストアの使用)

高レプリケーションデータストアは、データを複数のデータセンターに同期して保存することにより、読み書きについてのより高い可用性を提供します。バックエンドが変更されていますが、データストアAPIには全く変更はありません。使用しているデータストアがどちらであるかに関わらず、同じプログラミングインターフェイスを使用します。
高レプリケーションデータストアはより高いレプリケーションのためにより多くのコストがかかります(billing page for pricing detailsを参照)。高いコストのため、主に高い可用性を必要とするクリティカルなApp Engineアプリケーションを作成している開発者向けに高レプリケーションデータストアをお勧めしています。
しかしながら、高レプリケーションデータストアでは、エンティティグループに跨るクエリ(言い換えると、非エンシェスタクエリ)は古い結果を返す場合があります。高レプリケーション環境で一貫性の強いクエリの結果を返すために、単一のエンティティグループ上でクエリを発行する必要があります。このクエリのタイプは、エンシェスタ(祖先)クエリと呼ばれています。
エンシェスタクエリは、全ての操作はグループ全体に適用されることにより、エンティティグループが一貫性の単位であるために機能します。エンシェスタクエリはエンティティグループ全体が更新されるまでデータを返しません。このように、エンティティグループ上のエンシェスタクエリから返されるデータは強い一貫性を持ちます。
アプリケーションが強い一貫性を持つ結果に依存している場合、アプリケーションがエンティティを保存する方法を変更する必要がある場合があります。このページでは、高レプリケーションデータストアに保存されたデータを使用するためのベストプラクティスについて論じています。サンプルゲストブックアプリケーションを使って、マスター/スレーブと高レプリケーションデータストアがそれぞれどう機能する見てみましょう。

インストール不要・無料のKaede翻訳ツール:
http://kaedetrans.appspot.com/

2011年9月5日月曜日

Google App Engine のデータストアの選択(その5)

Google App Engineで使用するデータストアの種類の選択についての
翻訳の5回目です。


前回は、 HRDとマスター/スレーブの違いについての比較でした。
今回は、2種類のデータストアの選択の方法についてです。

データストアの選択
HRDは全ての新しいアプリケーションのデフォルトとなっています。既存のアプリケーションは新しいアプリケーションへのエンティティのコピーによってHRDに移行しなければなりません。マスター/スレーブデータストアの使用を望む場合、以下の方法で選択できます。

新しいアプリケーション向け
appengine.google.comで新しいアプリケーションを作成する時には、アプリケーションはHRDをデフォルトとして使用します。マスター/スレーブオプションを選択するには、Create an Application画面で選択します。
マスター/スレーブを選択するには、「編集」をクリックして「マスター/スレーブ」ラジオボタンを選択します。「アプリケーションの生成」をクリックすると、マスター/スレーブデータストアにデータを保存するようにアプリケーションを設定します。
注意!:このオプションは不可逆です。マスター/スレーブを選択してからHRDへの移行を望む場合、新しいアプリケーションの生成と現在のデータストアの内容を新しいアプリケーションにコピーしなければなりません。

既存のアプリケーション向け
HRDのアプリケーションをマスター/スレーブデータストアに移行したい場合、上記の方法で新しいアプリケーションを生成して、新しいアプリケーションに現在のデータストアのコピーが必要となります。
注意!:データストアのコピーは、現時点ではPythonのアプリケーションでのみ利用可能です。Java開発者は追加の構成手順を踏む必要があります。詳しくはJava開発者向けノートを参照してください。

インストール不要・無料のKaede翻訳ツール:
http://kaedetrans.appspot.com/

2011年9月4日日曜日

Google App Engineのデータストアの選択(その4)

Google App Engineで使用するデータストアの種類の選択についての
翻訳の4回目です。


前回は、マスター/スレーブデータストアについての説明でした。
以下は、HRDとマスター/スレーブの違いについての比較です。

以下の表ではHRDとマスター/スレーブデータストアの違いを示しています。
高レプリケーション(HRD) マスター/スレーブ
コスト
ストレージ 1x 1/3x
PutおよびDeleteのCPU 1x 5/8x
GetのCPU 1x 1x
QueryのCPU 1x 1x
パフォーマンス
Put/Deleteの待ち時間 1/2x - 1x 1x
Getの待ち時間 1x 1x
Queryの待ち時間 1x 1x
一貫性
Get/Put/Delete
多くのクエリ 結果による
Ancestor Query
時折発生する計画的
読み取り専用期間
不可
予期されないダウン時 非常にまれ。データ消失は無し まれ。ダウンタイム近辺で発生した書き込みに小さいパーセンテージで消失の可能性(イベントの後でリカバー可能)

インストール不要・無料のKaede翻訳ツール:
http://kaedetrans.appspot.com/

2011年9月1日木曜日

Google App Engine のデータストアの選択(その3)

Google App Engineで使用するデータストアの種類の選択についての
翻訳の3回目です。

前回は高レプリケーションデータストア(HRD)についての説明でしたが、
今回はもう一つの選択肢である
マスター/スレーブデータストアについてです。

マスター/スレーブデータストア
非同期に書き込んだデータを他のデータセンターに複製する、マスター/スレーブレプリケーションシステムを選択することも可能です。どの時点でも書き込み用に一つだけのデータセンターがマスターとなるので、このオプション(マスター/スレーブ)は全ての読み出しとクエリに強い一貫性を提供しますが、データセンターに問題が発生したり、計画的ダウンタイムの時に一時的にデータが利用不可能となります。

マスター/スレーブデータストアは以下のようなアプリケーションの限られたクラスにのみ適しています。
・データの高い可用性が求められない
・データストアの待ち時間の急増を許容することができる
・最低限のサービスのコストを負担する必要がある

インストール不要・無料のKaede翻訳ツール:
http://kaedetrans.appspot.com/

2011年8月28日日曜日

Google App Engineのデータストアの選択

日本語のドキュメントでは掲載されていないのですが、
Google App Engineのデータストアには、
機能の違うオプションが2つあるようです。

リンクはこちら

データストアの選択 (Java) Choosing a Datastore
App Engineは、異なる信頼性と一貫性を補償する2つのデータストレージのオプションを提供しています。このページでは、2つのオプションを比較し、アプリケーションにどちらのデータストアを適用する方法を説明します。
・データストレージのオプションの比較(Comparing the Data Storage Options)
・データストアの選択(Selecting a Datastore)

インストール不要・無料のKaede翻訳ツール:
http://kaedetrans.appspot.com/

2011年8月9日火曜日

Goole App Engine for Java のデータストアAPIを利用するクラスをテスト駆動開発する(その13)

それでは、ここで今までの内容を反映した
サンプルコードを掲載します。



import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import org.junit.After;
import org.junit.Before;
import org.junit.Test;

import com.google.appengine.api.datastore.DatastoreService;
import com.google.appengine.api.datastore.DatastoreServiceFactory;
import com.google.appengine.api.datastore.Entity;
import com.google.appengine.api.datastore.FetchOptions;
import com.google.appengine.api.datastore.Key;
import com.google.appengine.api.datastore.PreparedQuery;
import com.google.appengine.api.datastore.Query;
import com.google.appengine.api.datastore.Query.FilterOperator;
import com.google.appengine.tools.development.testing.LocalDatastoreServiceTestConfig;
import com.google.appengine.tools.development.testing.LocalServiceTestHelper;

/**
 * Google App Engine for Javaにおけるユニットテストのサンプルコード。
 */
public class LocalUnitTestSample {

	private static final String DATA_KIND = "sampleDataKind";

	private LocalServiceTestHelper helper = new LocalServiceTestHelper(new LocalDatastoreServiceTestConfig());

	private String propertyName = "propertyName";

	private String[] propertyValues = {"pValue1","pValue2","pValue3","pValue4","pValue5"};

	private DatastoreService ds;

	private List keyList;

	/**
	 * @throws java.lang.Exception
	 */
	@Before
	public void setUp() throws Exception {
		helper.setUp();

		//サンプルデータをデータストアに保存する
		putSampleData();
	}

	/**
	 * サンプルデータをデータストアに保存するメソッド。
	 */
	private void putSampleData() {
		keyList = new ArrayList();
		ds = DatastoreServiceFactory.getDatastoreService();
		for (int i = 0; i < propertyValues.length; i++) {
			Entity entity = new Entity(DATA_KIND);
			entity.setProperty(propertyName, propertyValues[i]);
			Key key = ds.put(entity);
			keyList.add(key);
		}
	}

	/**
	 * @throws java.lang.Exception
	 */
	@After
	public void tearDown() throws Exception {
		//サンプルデータをデータストアから削除する
		deleteSampleData();

		helper.tearDown();
	}

	/**
	 * サンプルデータをデータストアから削除するメソッド。
	 */
	private void deleteSampleData() {
		Iterator iter = keyList.iterator();
		while (iter.hasNext()){
			ds.delete(iter.next());
		}
	}

	@Test
	public void doTest(){
		//サンプルデータをデータストアから検索する
		for (int i = 0;i < propertyValues.length;i++){
			EntitySearch search = new EntitySearch(ds,DATA_KIND,propertyName);
			List entitiesList = search.getEntity(propertyValues[i]);
			assertEquals(1,entitiesList.size());
			Iterator iter = entitiesList.iterator();
			while (iter.hasNext()){
				Entity entity = iter.next();
				assertTrue(propertyValues[i].equals(entity.getProperty(propertyName)));
			}
		}
	}

	/**
	 * データストアから、設定された名前のプロパティが該当する
	 * エンティティを取得する機能を提供するクラス。
	 */
	public class EntitySearch {

		/**
		 * データストアサービス
		 */
		private DatastoreService ds;

		/**
		 * 探索するエンティティのカインド名を表す文字列フィールド
		 */
		private String kindName;

		/**
		 * 探索するプロパティの名前を表す文字列フィールド
		 */
		private String propertyName;

		/**
		 * データストアサービスと、探索するプロパティの名前を引数とするコンストラクタ。
		 * @param ds データストアサービスオブジェクト
		 * @param kindName 取得するエンティティのカインド名文字列
		 * @param propertyName 探索するプロパティ名を表す文字列
		 */
		public EntitySearch(DatastoreService ds, String kindName, String propertyName) {
			this.ds = ds;
			this.kindName = kindName;
			this.propertyName = propertyName;
		}

		/**
		 * データストアからエンティティを検索するメソッド。
		 * コンストラクタで設定したカインド、プロパティ名の値が
		 * 引数propertyValueと同一のエンティティを格納したリストを返します。
		 * @param propertyValue 検索条件となるプロパティの値オブジェクト
		 * @return コンストラクタで設定したプロパティが引数propertyValueと同一の値のエンティティのリスト
		 */
		public List getEntity(Object propertyValue) {
			Query query = new Query(kindName);
			query.addFilter(propertyName, FilterOperator.EQUAL, propertyValue);
			PreparedQuery prepare = ds.prepare(query);
			List entitiesList = prepare.asList(FetchOptions.Builder.withDefaults());
			return entitiesList;
		}

	}

} 

インストール不要・無料のKaede翻訳ツール:
http://kaedetrans.appspot.com/

2011年8月7日日曜日

Google App Engine for Java のデータストアAPIを利用するクラスをテスト駆動開発する(その12)

前回に引き続き、EntitySearchクラスの修正を行います。


メソッドgetEntity()内で、
クエリを生成する部分に修正する点があります。

コンパイル時に警告が出るのですが、
フィールドkindNameが参照されていないのです。

getEntity()内では、
エンティティ探索のためにクエリを生成しています。
クエリを生成するためにはコンストラクタで
new Query(String kind)
とするのですが、
引数の部分が
DATA_KIND
となっていて、LocalUnitTestSampleクラスの定数を参照しています。
(もし、EntitySearchクラスを内部クラスとしていなければ、
コンパイルエラーになります)

そこで、探索するエンティティのカインド名を
DATA_KINDから、kindNameに変更します。
そうすることで、EntitySearchクラスの内部から
LocalUnitTestSampleクラスのメンバを直接参照することは
なくなります。

インストール不要・無料のKaede翻訳ツール:
http://kaedetrans.appspot.com/

2011年8月4日木曜日

Google App Engine for Java のデータストアAPIを利用するクラスをテスト駆動開発する(その11)

前回の投稿で、テスト駆動開発の利点として、
回帰テストが容易に出来る、ということを挙げました。

その実践・・・というわけでもないですが、
サンプルコードを修正してみましょう。
修正、といいますが、つまり、忘れていた点があったんです。

作成したEntitySearchクラスのコンストラクタが
実装されていませんでした。
引数が何も使われないままになっていたんですね。

引数が使われないまま放置されていたのに、
テストを実行してみると成功します。
この理由は、
EntitySearchクラスがLocalUnitTestSampleクラスの
内部クラスであることが原因です。

もし、EntitySearchクラスを内部クラスではなく、
別の独立したクラスとすると
コンパイルエラーとなります。

メソッドgetEntity()の内部で、
変数ds,kindName,propertyNameを解決できないはずです。

そこで、コンストラクタで渡された引数を
フィールドとして保持することにします。
private DatastoreService ds;

private String kindName;

private String propertyName;

public EntitySearch(DatastoreService ds, String kindName, String propertyName) {
 this.ds = ds;
 this.kindName = kindName;
 this.propertyName = propertyName;
}
フィールドds,kindName,propertyNameを宣言して、
コンストラクタで引数の値を代入します。

これで、メソッドgetEntity()でのコンパイルエラーが解消されます。

インストール不要・無料のKaede翻訳ツール:
http://kaedetrans.appspot.com/

2011年7月25日月曜日

Google App Engine for Java のデータストアAPIを利用するクラスをテスト駆動開発してみる(その10)

先に進む前に、ソースコードを掲載します。

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import org.junit.After;
import org.junit.Before;
import org.junit.Test;

import com.google.appengine.api.datastore.DatastoreService;
import com.google.appengine.api.datastore.DatastoreServiceFactory;
import com.google.appengine.api.datastore.Entity;
import com.google.appengine.api.datastore.FetchOptions;
import com.google.appengine.api.datastore.Key;
import com.google.appengine.api.datastore.PreparedQuery;
import com.google.appengine.api.datastore.Query;
import com.google.appengine.api.datastore.Query.FilterOperator;
import com.google.appengine.tools.development.testing.LocalDatastoreServiceTestConfig;
import com.google.appengine.tools.development.testing.LocalServiceTestHelper;

/**
 * Google App Engine for Javaにおけるユニットテストのサンプルコード。
 */
public class LocalUnitTestSample {

 private static final String DATA_KIND = "sampleDataKind";

 private LocalServiceTestHelper helper = new LocalServiceTestHelper(new LocalDatastoreServiceTestConfig());

 //private String[] propertyNames = {"pName1","pName2","pName3","pName4","pName5"};
 private String propertyName = "propertyName";

 private String[] propertyValues = {"pValue1","pValue2","pValue3","pValue4","pValue5"};

 private DatastoreService ds;

 private List<key> keyList;

 /**
  * @throws java.lang.Exception
  */
 @Before
 public void setUp() throws Exception {
  helper.setUp();

  //サンプルデータをデータストアに保存する
  putSampleData();
 }

 /**
  * サンプルデータをデータストアに保存するメソッド。
  */
 private void putSampleData() {
  keyList = new ArrayList<key>();
  ds = DatastoreServiceFactory.getDatastoreService();
  for (int i = 0; i < propertyValues.length; i++) {
   Entity entity = new Entity(DATA_KIND);
   entity.setProperty(propertyName, propertyValues[i]);
   Key key = ds.put(entity);
   keyList.add(key);
  }
 }

 /**
  * @throws java.lang.Exception
  */
 @After
 public void tearDown() throws Exception {
  //サンプルデータをデータストアから削除する
  deleteSampleData();

  helper.tearDown();
 }

 /**
  * サンプルデータをデータストアから削除するメソッド。
  */
 private void deleteSampleData() {
  Iterator<key> iter = keyList.iterator();
  while (iter.hasNext()){
   ds.delete(iter.next());
  }
 }

 @Test
 public void doTest(){
  //サンプルデータをデータストアから検索する
  for (int i = 0;i < propertyValues.length;i++){
   EntitySearch search = new EntitySearch(ds,DATA_KIND,propertyName);
   List<entity> entitiesList = search.getEntity(propertyValues[i]);
   assertEquals(1,entitiesList.size());
   Iterator<entity> iter = entitiesList.iterator();
   while (iter.hasNext()){
    Entity entity = iter.next();
    assertTrue(propertyValues[i].equals(entity.getProperty(propertyName)));
   }
  }
 }

 /**
  * データストアから、設定された名前のプロパティが該当する
  * エンティティを取得する機能を提供するクラス。
  */
 public class EntitySearch {

  /**
   * データストアサービスと、探索するプロパティの名前を引数とするコンストラクタ。
   * @param ds データストアサービスオブジェクト
   * @param kindName 取得するエンティティのカインド名文字列
   * @param propertyName 探索するプロパティ名を表す文字列
   */
  public EntitySearch(DatastoreService ds, String kindName, String propertyName) {

  }

  /**
   * データストアからエンティティを検索するメソッド。
   * コンストラクタで設定したカインド、プロパティ名の値が
   * 引数propertyValueと同一のエンティティを格納したリストを返します。
   * @param propertyValue 検索条件となるプロパティの値オブジェクト
   * @return コンストラクタで設定したプロパティが引数propertyValueと同一の値のエンティティのリスト
   */
  public List<entity> getEntity(Object propertyValue) {
   Query query = new Query(DATA_KIND);
   query.addFilter(propertyName, FilterOperator.EQUAL, propertyValue);
   PreparedQuery prepare = ds.prepare(query);
   List<entity> entitiesList = prepare.asList(FetchOptions.Builder.withDefaults());
   return entitiesList;
  }

 }

}


インストール不要・無料のKaede翻訳ツール:
http://kaedetrans.appspot.com/