データ書き込み用サーブレット
サーブレットは、先ほどのリスト2をリスト6のように変えます。
package guestbook; import java.io.IOException; import java.util.Date; import javax.jdo.PersistenceManager; // 【1】 import javax.servlet.http.*; import com.google.appengine.api.users.User; import com.google.appengine.api.users.UserService; import com.google.appengine.api.users.UserServiceFactory; import guestbook.Greeting; // 【2】 import guestbook.PMF; // 【2】 public class SignGuestbookServlet extends HttpServlet { public void doPost(HttpServletRequest req, HttpServletResponse resp) throws IOException { UserService userService = UserServiceFactory.getUserService(); User user = userService.getCurrentUser(); String content = req.getParameter("content"); Date date = new Date(); // 【3】始まり Greeting greeting = new Greeting(user, content, date); PersistenceManager pm = PMF.get().getPersistenceManager(); try { pm.makePersistent(greeting); } finally { pm.close(); } // 【3】終わり resp.sendRedirect("/guestbook.jsp"); } }
リスト6でデータストアへのアクセスに直接関係するコード記述は、【1】〜【3】がすべてです。
【1】でPersistenceManagerクラスをインポートし、次に【2】で、ここで作成したGreetingとPMFクラスをインポートします。
【3】では、最初に作成したGreetingクラスのインスタンスgreetingを生成します。前に見たように、コンストラクタ呼び出しによって、登録するデータ項目の値が永続化指定のメンバ変数にセットされます。次の行では、これも作成済みのPMクラスのgetメソッドからPersistenceManagerのインスタンスpmを生成し、最後にpmインスタンスのメソッドmakePersistentを、引数にgrettingを指定して実行すると、データストアへの登録が行われます。
【3】での登録(永続化)処理終了後、「resp.sendRedirect("/guestbook.jsp");」のリダイレクトでJSPの表示に切り替わります。この中では、直前に登録したばかりのデータをJSPで検索・表示することになります。
BigtableデータをSQLライクに参照できるJDOQLとは?
以上がデータストアへの登録処理でしたが、次にJSPでのデータの参照について見ていきます。リスト1をリスト7のようにデータストア・エンティティの参照表示ができるように変えます。
<%@ page contentType="text/html;charset=UTF-8" language="java" %> <%@ page import="java.util.List" %> <%@ page import="javax.jdo.PersistenceManager" %> <%@ page import="com.google.appengine.api.users.User" %> <%@ page import="com.google.appengine.api.users.UserService" %> <%@ page import="com.google.appengine.api.users.UserServiceFactory" %> <%@ page import="guestbook.Greeting" %> <%@ page import="guestbook.PMF" %> <html> <body> <% UserService userService = UserServiceFactory.getUserService(); User user = userService.getCurrentUser(); if (user != null) { %> <p>今日は <%= user.getNickname() %>! (ここから<a href="<%= userService.createLogoutURL(request.getRequestURI()) %>">サインアウト</a>できます。)</p> <% } else { %> <p>今日は!<a href="<%= userService.createLoginURL(request.getRequestURI()) %>">サインイン</a>すると送信メッセージがサインイン名付で表示されます。</p> <% } %> <% PersistenceManager pm = PMF.get().getPersistenceManager(); // 【1】 String query = "select from " + Greeting.class.getName()+ " order by date"; // 【1】 List<Greeting> greetings = (List<Greeting>) pm.newQuery(query).execute(); // 【1】 if (greetings.isEmpty()) { %> <p>The guestbook has no messages.</p> <% } else { for (Greeting g : greetings) { if (g.getAuthor() == null) { %> <p>匿名ユーザの書き込み</p> <% } else { %> <p><b><%= g.getAuthor().getNickname() %></b>の書き込み:</p> <% } %> <blockquote><%= g.getContent() %></blockquote> <% } } pm.close(); %> <form action="/sign" method="post"> <div><textarea name="content" rows="3" cols="60"></textarea></div> <div><input type="submit" value="メッセージ送信" /></div> </form> </body> </html>
リスト6で赤太字の部分がデータストアアクセスに関係する部分ですが、その中でも【1】がポイントになります。
【1】の最初の行では、作成したPMクラスを使用してインスタンスpmを生成しています。これは、前の登録処理でも行われていたもので、データストアアクセスで必須の定型的な処理です。
次の行で文字列queryにセットされる「select……」の記述は、RDBのSQL文に似た書式ですが、JDOにアクセスする文なので「JDOQL」と呼ばれます。
ここでのJDOQLは、サーブレットで登録した内容を全件・検索して日付け昇順に表示する処理内容となっています。fromの後の「Greeting.class.getName()」の部分は、GAEサイトのサンプル記述によるものです。これを「guestbook.Greeting」に変え、JDOQLを次のように書き換えても問題ありません。
String query = "select from guestbook.Greeting order by date";
つまり、アクセス対象となるデータストアオブジェクトは「パッケージ名.データクラス名」になっているのです。
3行目では、2行目で設定したqueryを引数にデーストア検索を実行します。返される値はコレクションとなり、List型で受け取ります。後は、リストから順にデータを取り出して処理します。「(if (g.getAuthor() == null))」で、サインインユーザーか否かで表示内容を切り分けながら、1件ずつ書き込み内容である「g.getContent()」を表示していきます。
次回は、jQueryでAppEngineアプリをAjax化!
今回はJSPでのUI表示とBigtableへのアクセスを中心に見てきましたが、次回はjQueryと組み合わせてみたいと思います。
ご存じだとは思いますが、AjaxはGoogleマップによって世に広められ、Googleドキュメントなどにも使われています。GAEjのUIにもAjax(jQuery)を適用してリッチクライアントにしていきましょう。またBigtableについても、もっと理解を深めていきたいところです。次回は、このような内容について解説していく予定です。
Copyright © ITmedia, Inc. All Rights Reserved.