データ書き込み用サーブレット
サーブレットは、先ほどのリスト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.