Google Apps Engine/JavaのData Storeで所有関係を作ってみる(1:1)
Google Apps Engine/Java(GAE/J)のData Storeで1:1の所有関係を作ってみる。
先のログに書いたように、所有関係も(主キー上で表現される)「ルートエンティティーからのパス」概念に帰着される。
公式HP(こことかここ)をみると、所有側インスタンスの1プロパティーに、被所有のインスタンス(の参照)を代入し、所有側をストアすることで、所有関係が成立する、とある。この際、ストアされるのは、所有側のインスタンス(エンティティー)と被所有のインスタンス(エンティティー)の2つとなり、被所有のインスタンスのキーは(自動的に所有側の子孫として)設定される。
データをストア/取り出し/削除するサンプルは、前回同様にサーブレット上に実装する。今回は、1:1の所有関係にまつわる操作を、以下の画面から行う。
この画面からは、
- Rootエンティティーのストア
- 所有側エンティティー(Friends)、被所有のエンティティー(FriendsInfo)のストア
- 主キーを生成して、所有側エンティティーを取り出す、同時にそれに紐付く被所有のエンティティーのプロパティー値をとりだす。
- 主キーを生成して、被所有のエンティティーを取り出す。
- JDOQLを使って、所有/被所有のエンティティーの一覧を作成する。
- 所有側のエンティティーを削除する。(カスケードデリートのテスト)
- 所有側のエンティティーと被所有のエンティティーを、それぞれ明示的に削除する。
- Rootエンティティーを削除する。
を行うこととした。
プロジェクトの作成
Web Application Projectを新規に作成する。GWTは使わないので、チェックをはずす。
必要であれば、ロギングの定義を変えるなどする。
Rootエンティティー
まず、Rootとするエンティティーを以下のようにtest.entitiesパッケージに作成した。
package test.entities; import javax.jdo.annotations.PersistenceCapable; import javax.jdo.annotations.IdentityType; import javax.jdo.annotations.IdGeneratorStrategy; import javax.jdo.annotations.PrimaryKey; import javax.jdo.annotations.Persistent; import com.google.appengine.api.datastore.Key; /********************************* * * エンティティーグループを定義するRootエンティティー * * @author * tetsuya_odaka (EzoGP) <br> *********************************/ @PersistenceCapable(identityType=IdentityType.APPLICATION) public class RootTO { /* * 親エンティティーのキーはKeyか、String */ @PrimaryKey @Persistent(valueStrategy = IdGeneratorStrategy.IDENTITY) private Key parentKey; @Persistent private String firstName; @Persistent private String lastName; /** * コンストラクタ * */ public RootTO(String firstName, String lastName) { this.firstName = firstName; this.lastName = lastName; } public Key getParentKey() { return parentKey; } public void setParentKey(Key parentKey) { this.parentKey = parentKey; } public String getFirstName() { return firstName; } public void setFirstName(String firstName) { this.firstName = firstName; } public String getLastName() { return lastName; } public void setLastName(String lastName) { this.lastName = lastName; } }
Friendsエンティティー
次に、Rootで規定されるエンティティー・グループのエンティティーとして、Friends.javaを以下のように作成した。
このエンティティーは、所有関係において所有者(所有する側)となる。
package test.entities; import java.util.Date; import javax.jdo.annotations.PersistenceCapable; import javax.jdo.annotations.IdentityType; import javax.jdo.annotations.IdGeneratorStrategy; import javax.jdo.annotations.PrimaryKey; import javax.jdo.annotations.Persistent; import javax.jdo.annotations.Extension; import com.google.appengine.api.datastore.Key; /********************************* * * エンティティー(所有) * * @author * tetsuya_odaka (EzoGP) <br> *********************************/ @PersistenceCapable(identityType=IdentityType.APPLICATION) public class Friends { @PrimaryKey @Persistent(valueStrategy = IdGeneratorStrategy.IDENTITY) private Key key; @Persistent @Extension(vendorName="datanucleus",key="gae.parent-pk",value="true") private Key parentKey; @Persistent private String firstName; @Persistent private String lastName; @Persistent private FriendsInfo friendsInfo; @Persistent private Date entryDate; /** * コンストラクタ * */ public Friends(String firstName, String lastName,Date entryDate) { this.firstName = firstName; this.lastName = lastName; this.entryDate = entryDate; } /** * setter/getter */ public String getFirstName() { return firstName; } public void setFirstName(String firstName) { this.firstName = firstName; } public String getLastName() { return lastName; } public void setLastName(String lastName) { this.lastName = lastName; } public Date getEntryDate() { return entryDate; } public void setEntryDate(Date entryDate) { this.entryDate = entryDate; } public FriendsInfo getFriendsInfo() { return friendsInfo; } public void setFriendsInfo(FriendsInfo friendsInfo) { this.friendsInfo = friendsInfo; } public Key getKey() { return key; } public void setKey(Key key) { this.key = key; } public Key getParentKey() { return parentKey; } public void setParentKey(Key parentKey) { this.parentKey = parentKey; } }
FriendsInfoエンティティー
最後に、Friends.javaに所有されるエンティティ(被所有)として、FriendsInfo.javaを以下のように作成した。
package test.entities; import java.util.Date; import javax.jdo.annotations.Extension; import javax.jdo.annotations.IdGeneratorStrategy; import javax.jdo.annotations.PersistenceCapable; import javax.jdo.annotations.IdentityType; import javax.jdo.annotations.PrimaryKey; import javax.jdo.annotations.Persistent; import com.google.appengine.api.datastore.Key; /********************************* * * エンティティー(被所有) * * tetsuya_odaka (EzoGP) <br> *********************************/ @PersistenceCapable(identityType=IdentityType.APPLICATION) public class FriendsInfo { @PrimaryKey @Persistent(valueStrategy = IdGeneratorStrategy.IDENTITY) private Key key; @Persistent @Extension(vendorName="datanucleus",key="gae.parent-pk",value="true") private Key parentKey; @Persistent private String attrName; @Persistent private Date entryDate; /** * コンストラクタ * */ public FriendsInfo(String attrName ,Date entryDate) { this.attrName = attrName; this.entryDate = entryDate; } /** * setter/getter */ public String getAttrName() { return attrName; } public void setAttrName(String attrName) { this.attrName = attrName; } public Date getEntryDate() { return entryDate; } public void setEntryDate(Date entryDate) { this.entryDate = entryDate; } public Key getKey() { return key; } public void setKey(Key key) { this.key = key; } public Key getParentKey() { return parentKey; } public void setParentKey(Key parentKey) { this.parentKey = parentKey; } }
Rootエンティティーの登録
package test; import java.io.IOException; import java.io.PrintWriter; import javax.jdo.PersistenceManager; import javax.servlet.http.*; import com.google.appengine.api.datastore.Key; import com.google.appengine.api.datastore.KeyFactory; import test.entities.RootTO; @SuppressWarnings("serial") public class GaeDataStoreCreateParentServlet extends HttpServlet { public void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException { RootTO to = new RootTO("tetsuya","odaka"); /* * keyを生成 */ // 文字を種(たね)にするときは、数字が先頭だと怒る。 Key key =KeyFactory.createKey(RootTO.class.getSimpleName(), "parentKey"); to.setParentKey(key); PersistenceManager pm = PMF.get().getPersistenceManager(); // 親エンティティーを登録 boolean flg = false; try{ pm.makePersistent(to); flg = true; }finally{ pm.close(); } resp.setContentType("text/html; charset=utf-8"); PrintWriter out = resp.getWriter(); out.println("<html><head>"); out.println("<title>Rootエンティティーの登録</title>"); out.println("</head>"); out.println("<body>"); out.println("<h2>Rootエンティティーの登録</h2>"); if(flg){ out.println("Rootエンティティーを登録しました。"); }else{ out.println("Rootエンティティーに失敗しました。"); } out.println("</body></html>"); } }
Friends, FriendsInfoエンティティーの登録
以下のサーブレットで、所有者となるFriendsと被所有者のFriendsInfoのストアを行う。
- Friendsのインスタンス化
- Friendsのパラメータ(プロパティー)にFriendsInfoのインスタンス(の参照)をSet
- FriendsをPersistenseManagerを使ってストアする。
ここで注目すべきは
である。
package test; import java.io.IOException; import java.io.PrintWriter; import java.util.Date; import javax.jdo.PersistenceManager; import javax.servlet.http.*; import com.google.appengine.api.datastore.Key; import com.google.appengine.api.datastore.KeyFactory; import test.entities.Friends; import test.entities.FriendsInfo; import test.entities.RootTO; @SuppressWarnings("serial") public class GaeDataStoreCreateChildrenServlet extends HttpServlet { public void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException { /** * 所有されるエンティティの生成 */ FriendsInfo fi1 = new FriendsInfo("属性1",new Date()); FriendsInfo fi2 = new FriendsInfo("属性2",new Date()); FriendsInfo fi3 = new FriendsInfo("属性3",new Date()); // fiキーの生成(1) KeyFactory.Builder kb = new KeyFactory.Builder(FriendsInfo.class.getSimpleName(), "info1"); Key key1 = kb.getKey(); // fiキーのセット(1) fi1.setKey(key1); // fiキーの生成(2) kb = new KeyFactory.Builder(FriendsInfo.class.getSimpleName(), "info2"); Key key2 = kb.getKey(); // fiキーのセット(2) fi2.setKey(key2); // fiキーの生成(3) kb = new KeyFactory.Builder(FriendsInfo.class.getSimpleName(), "info3"); Key key3 = kb.getKey(); // fiキーのセット(3) fi3.setKey(key3); PersistenceManager pm = PMF.get().getPersistenceManager(); /** * 所有する側のエンティティの生成 */ Friends child1 = new Friends("次郎","鈴木",new Date()); Friends child2 = new Friends("太郎","佐藤",new Date()); Friends child3 = new Friends("三郎","山田",new Date()); // キーの生成(1) kb = new KeyFactory.Builder(RootTO.class.getSimpleName(), "parentKey"); kb.addChild(Friends.class.getSimpleName(), "friend1"); Key key4 = kb.getKey(); // キーのセット(1) child1.setKey(key4); // キーの生成(2) kb = new KeyFactory.Builder(RootTO.class.getSimpleName(), "parentKey"); kb.addChild(Friends.class.getSimpleName(), "friend2"); Key key5 = kb.getKey(); // キーのセット(2) child2.setKey(key5); // キーの生成(3) kb = new KeyFactory.Builder(RootTO.class.getSimpleName(), "parentKey"); kb.addChild(Friends.class.getSimpleName(), "friend3"); Key key6 = kb.getKey(); // 子のキーのセット(3) child3.setKey(key6); // FriendsInfoのセット // (注)こうしてセットしてmakePersistentすれば、エンティティー // が生成され、キーには親のキーが負荷される。(親キーもセットされる。entity beanの設定より) child1.setFriendsInfo(fi1); child2.setFriendsInfo(fi2); child3.setFriendsInfo(fi3); boolean flag=false; try{ pm.makePersistent(child1); pm.makePersistent(child2); pm.makePersistent(child3); flag=true; }finally{ pm.close(); } resp.setContentType("text/html; charset=utf-8"); PrintWriter out = resp.getWriter(); // 出力部 out.println("<html><head>"); out.println("<title>Friends,FriendsInfoエンティティーの登録</title>"); out.println("</head>"); out.println("<body>"); out.println("<h2>Friends,FriendsInfoエンティティーの登録</h2>"); if(flag){ out.println("Friends,FriendsInfoエンティティーを登録しました。"); }else{ out.println("Friends,FriendsInfoエンティティーの登録に失敗しました。"); } out.println("</body></html>"); } }
主キーによりFriendsエンティティーを取得する。
以下のサーブレットにより主キーを生成して、Data StoreからFriendsエンティティーを取得する。
主キーが、Rootからのパスを含んだKeyオブジェクトとなるため、KeyFactory.BuilderにaddChildしてキーを生成する。
package test; import java.io.IOException; import java.io.PrintWriter; import javax.jdo.PersistenceManager; import javax.servlet.http.*; import com.google.appengine.api.datastore.Key; import com.google.appengine.api.datastore.KeyFactory; import test.entities.Friends; import test.entities.RootTO; @SuppressWarnings("serial") public class GaeDataStoreGetFriendsServlet extends HttpServlet { public void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException { PersistenceManager pm = PMF.get().getPersistenceManager(); // キーの生成 KeyFactory.Builder kb = new KeyFactory.Builder(RootTO.class.getSimpleName(), "parentKey"); kb.addChild(Friends.class.getSimpleName(), "friend2"); Key key = kb.getKey(); // オブジェクトの取得 Friends friend = pm.getObjectById(Friends.class, key); String firstName = friend.getFirstName(); String lastName = friend.getLastName(); String keyString = friend.getKey().toString(); String parentKeyString = friend.getParentKey().toString(); String attrName = friend.getFriendsInfo().getAttrName(); pm.close(); resp.setContentType("text/html; charset=utf-8"); PrintWriter out = resp.getWriter(); out.println("<html><head>"); out.println("<title>Friendsエンティティーの取得</title>"); out.println("</head>"); out.println("<body>"); out.println("<h2>キーによるFriendsエンティティーの取得</h2>"); out.println("<table border=1>"); out.println("<tr><td>Friendsエンティティー</td><td>"+Friends.class.getSimpleName()+"</td></tr>"); out.println("<tr><td>主キー</td><td>"+keyString+"</td></tr>"); out.println("<tr><td>親キー</td><td>"+parentKeyString+"</td></tr>"); out.println("<tr><td>名</td><td>"+firstName+"</td></tr>"); out.println("<tr><td>姓</td><td>"+lastName+"</td></tr>"); out.println("<tr><td>属性名</td><td>"+attrName+"</td></tr>"); out.println("</table></body></html>"); } }
これを実行した結果は、以下の画面となる。
主キーによりFriendsInfoエンティティーを取得する。
以下のサーブレットにより、主キーを生成して、Data StoreからFriendsInfoエンティティーを取得する。FriendsInfoはFriendsの下位に位置づけられるため、キーの生成はRoot=>Friends=>FriendsInfoとなる。
package test; import java.io.IOException; import java.io.PrintWriter; import javax.jdo.PersistenceManager; import javax.servlet.http.*; import com.google.appengine.api.datastore.Key; import com.google.appengine.api.datastore.KeyFactory; import test.entities.Friends; import test.entities.FriendsInfo; import test.entities.RootTO; @SuppressWarnings("serial") public class GaeDataStoreGetFriendsInfoServlet extends HttpServlet { public void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException { PersistenceManager pm = PMF.get().getPersistenceManager(); // キーの生成 KeyFactory.Builder kb = new KeyFactory.Builder(RootTO.class.getSimpleName(), "parentKey"); kb.addChild(Friends.class.getSimpleName(), "friend2"); kb.addChild(FriendsInfo.class.getSimpleName(), "info2"); Key key = kb.getKey(); // オブジェクトの取得 FriendsInfo friendInfo = pm.getObjectById(FriendsInfo.class, key); String attrName = friendInfo.getAttrName(); String keyString = friendInfo.getKey().toString(); String parentKeyString = friendInfo.getParentKey().toString(); pm.close(); resp.setContentType("text/html; charset=utf-8"); PrintWriter out = resp.getWriter(); out.println("<html><head>"); out.println("<title>FriendsInfoエンティティーの取得</title>"); out.println("</head>"); out.println("<body>"); out.println("<h2>キーによるFriendsInfoエンティティーの取得</h2>"); out.println("<table border=1>"); out.println("<tr><td>FriendsInfoエンティティー</td><td>"+FriendsInfo.class.getSimpleName()+"</td></tr>"); out.println("<tr><td>主キー</td><td>"+keyString+"</td></tr>"); out.println("<tr><td>親キー</td><td>"+parentKeyString+"</td></tr>"); out.println("<tr><td>属性名</td><td>"+attrName+"</td></tr>"); out.println("</table></body></html>"); } }
これを実行した結果は、以下の画面となる。
JDOQLによりFriends, FriendsInfoエンティティーを取得する。
JDOQLのクエリにより、ストアされているFriendsエンティティー、FriendsInfoエンティティーを取り出して表示する。
package test; import java.io.IOException; import java.io.PrintWriter; import java.util.List; import javax.jdo.PersistenceManager; import javax.jdo.Query; import javax.servlet.http.*; import test.entities.Friends; import test.entities.FriendsInfo; @SuppressWarnings("serial") public class GaeDataStoreQueryServlet extends HttpServlet { @SuppressWarnings("unchecked") public void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException { resp.setContentType("text/html; charset=utf-8"); PrintWriter out = resp.getWriter(); out.println("<html><head>"); out.println("<title>Friends,FriendsInfoエンティティーのクエリー</title>"); out.println("</head>"); out.println("<body>"); out.println("<h2>クエリーによるFriends,FriendsInfoエンティティーの取得</h2>"); out.println("<h3>Friendsエンティティー</h3>"); PersistenceManager pm = PMF.get().getPersistenceManager(); /** * Friendsエンティティーに対するクエリの実行 */ Query query = pm.newQuery(Friends.class); query.setOrdering("firstName asc"); try{ List<Friends> list = (List<Friends>)query.execute(); for(Friends friend : list){ String firstName = friend.getFirstName(); String lastName = friend.getLastName(); String attrName = friend.getFriendsInfo().getAttrName(); String keyString = friend.getKey().toString(); String parentKeyString = friend.getParentKey().toString(); out.println("<table border=1>"); out.println("<tr><td>Friendsエンティティー</td><td>"+Friends.class.getSimpleName()+"</td></tr>"); out.println("<tr><td>主キー</td><td>"+keyString+"</td></tr>"); out.println("<tr><td>親キー</td><td>"+parentKeyString+"</td></tr>"); out.println("<tr><td>名</td><td>"+firstName+"</td></tr>"); out.println("<tr><td>姓</td><td>"+lastName+"</td></tr>"); out.println("<tr><td>属性名</td><td>"+attrName+"</td></tr>"); out.println("</table></br>"); } }finally{ query.closeAll(); } out.println("<br><br>"); out.println("<h3>FriendsInfoエンティティー</h3>"); /** * FriendsInfoエンティティーに対するクエリの実行 */ query = pm.newQuery(FriendsInfo.class); try{ List<FriendsInfo> list = (List<FriendsInfo>)query.execute(); for(FriendsInfo friendsInfo : list){ String keyString = friendsInfo.getKey().toString(); String parentKeyString = friendsInfo.getParentKey().toString(); String attrName = friendsInfo.getAttrName(); out.println("<table border=1>"); out.println("<tr><td>FriendsInfoエンティティー</td><td>"+FriendsInfo.class.getSimpleName()+"</td></tr>"); out.println("<tr><td>主キー</td><td>"+keyString+"</td></tr>"); out.println("<tr><td>親キー</td><td>"+parentKeyString+"</td></tr>"); out.println("<tr><td>属性名</td><td>"+attrName+"</td></tr>"); out.println("</table></br>"); } }finally{ query.closeAll(); pm.close(); } out.println("</body></html>"); } }
これを実行した結果は、以下の画面となる。
Friendsエンティティーを全て削除する(カスケード削除)
以下のプログラムにより、Friendsエンティティーを全て削除する。
この処理にともなって、被所有の関係にあるFriendsInfoが削除される(カスケード削除、リカーシブ削除)されることを期待したが、FriendsInfoが残ってしまう、という結果を得た。
(これは、この処理の実行後、JDOQLを画面から発行すれば確認できる)
package test; import java.io.IOException; import java.io.PrintWriter; import java.util.List; import javax.jdo.PersistenceManager; import javax.jdo.Query; import javax.servlet.http.*; import test.entities.Friends; @SuppressWarnings("serial") public class GaeDataStoreCascadeDaleteServlet extends HttpServlet { @SuppressWarnings("unchecked") public void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException { resp.setContentType("text/html; charset=utf-8"); PrintWriter out = resp.getWriter(); out.println("<html><head>"); out.println("<title>カスケードデリート</title>"); out.println("</head>"); out.println("<body>"); out.println("<h2>エンティティーのカスケードデリート</h2>"); PersistenceManager pm = PMF.get().getPersistenceManager(); Query query = pm.newQuery(Friends.class); try{ List<Friends> list = (List<Friends>)query.execute(); pm.deletePersistentAll(list); }finally{ query.closeAll(); pm.close(); } out.println("</body></html>"); } }
トランザクションを使ってFriends,FrindsInfoエンティティーを全て削除する
Friends, FriendsInfoが同一のエンティティー・グループに属し、1つのトランザクションで削除処理が行えることを確認した。
package test; import java.io.IOException; import java.io.PrintWriter; import java.util.List; import javax.jdo.PersistenceManager; import javax.jdo.Query; import javax.servlet.http.*; import test.entities.Friends; import test.entities.FriendsInfo; @SuppressWarnings("serial") public class GaeDataStoreTransactionServlet extends HttpServlet { @SuppressWarnings("unchecked") public void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException { resp.setContentType("text/html; charset=utf-8"); PrintWriter out = resp.getWriter(); out.println("<html><head>"); out.println("<title>トランザクション</title>"); out.println("</head>"); out.println("<body>"); out.println("<h2>トランザクションによるFriends,FriendsInfoエンティティーの削除</h2>"); PersistenceManager pm = PMF.get().getPersistenceManager(); Query query = pm.newQuery(Friends.class); try{ // トランザクションの開始 pm.currentTransaction().begin(); List<Friends> list = (List<Friends>)query.execute(); for(Friends friend : list){ FriendsInfo friendsInfo = friend.getFriendsInfo(); // FriendsInfoの削除 pm.deletePersistent(friendsInfo); // Friendsの削除 pm.deletePersistent(friend); } // 全部削除できたらコミット pm.currentTransaction().commit(); out.println("処理が正常に終了しました。"); }finally{ if(pm.currentTransaction().isActive()){ // ロールバック pm.currentTransaction().rollback(); out.println("処理が異常終了しました。"); } query.closeAll(); pm.close(); } out.println("</body></html>"); } }
Rootエンティティーの削除
rootエンティティーを削除する。
package test; import java.io.IOException; import java.io.PrintWriter; import javax.jdo.PersistenceManager; import javax.servlet.http.*; import com.google.appengine.api.datastore.Key; import com.google.appengine.api.datastore.KeyFactory; import test.entities.RootTO; @SuppressWarnings("serial") public class GaeDataStoreDeleteParentServlet extends HttpServlet { public void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException { PersistenceManager pm = PMF.get().getPersistenceManager(); // オブジェクトの取得 Key key = KeyFactory.createKey(RootTO.class.getSimpleName(), "parentKey"); RootTO to = pm.getObjectById(RootTO.class, key); // オブジェクトの削除 try{ pm.deletePersistent(to); }finally{ pm.close(); } resp.setContentType("text/html; charset=utf-8"); PrintWriter out = resp.getWriter(); out.println("<html><head>"); out.println("<title>Rootエンティティーの削除</title>"); out.println("</head>"); out.println("<body>"); out.println("<h2>Rootエンティティーの削除</h2>"); out.println("Rootエンティティーを削除しました。"); out.println("</body></html>"); } }
web.xml
war/WEB-INF/web.xmlにサーブレットとマッピング定義を行う。
<?xml version="1.0" encoding="utf-8"?> <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" version="2.5"> <!--// Parent(Root)エンティティーのストア --> <servlet> <servlet-name>GaeDataStoreCreateParent</servlet-name> <servlet-class>test.GaeDataStoreCreateParentServlet</servlet-class> </servlet> <!--// Parent(Root)エンティティーの削除 --> <servlet> <servlet-name>GaeDataStoreDeleteParent</servlet-name> <servlet-class>test.GaeDataStoreDeleteParentServlet</servlet-class> </servlet> <!--// Friends,FriendsInfoエンティティーのストア --> <servlet> <servlet-name>GaeDataStoreCreateChidren</servlet-name> <servlet-class>test.GaeDataStoreCreateChildrenServlet</servlet-class> </servlet> <!--// 主キーによる、Friendsエンティティーの取得 --> <servlet> <servlet-name>GaeDataStoreGetFriends</servlet-name> <servlet-class>test.GaeDataStoreGetFriendsServlet</servlet-class> </servlet> <!--// 主キーによる、FriendsInfoエンティティーの取得 --> <servlet> <servlet-name>GaeDataStoreGetFriendsInfo</servlet-name> <servlet-class>test.GaeDataStoreGetFriendsInfoServlet</servlet-class> </servlet> <!--// JDOQLによる、Friends,FriendsInfoエンティティーの取得 --> <servlet> <servlet-name>GaeDataStoreQuery</servlet-name> <servlet-class>test.GaeDataStoreQueryServlet</servlet-class> </servlet> <!--// Friends,FriendsInfoエンティティーの削除(トランザクション) --> <servlet> <servlet-name>GaeDataStoreTransaction</servlet-name> <servlet-class>test.GaeDataStoreTransactionServlet</servlet-class> </servlet> <!--// Friendsエンティティーの削除(カスケード削除のテスト) --> <servlet> <servlet-name>GaeDataStoreCascadeDalete</servlet-name> <servlet-class>test.GaeDataStoreCascadeDaleteServlet</servlet-class> </servlet> <!--// 以下はサーブレット・マッピング --> <servlet-mapping> <servlet-name>GaeDataStoreCreateParent</servlet-name> <url-pattern>/createparent</url-pattern> </servlet-mapping> <servlet-mapping> <servlet-name>GaeDataStoreDeleteParent</servlet-name> <url-pattern>/deleteparent</url-pattern> </servlet-mapping> <servlet-mapping> <servlet-name>GaeDataStoreCreateChidren</servlet-name> <url-pattern>/createchidren</url-pattern> </servlet-mapping> <servlet-mapping> <servlet-name>GaeDataStoreGetFriends</servlet-name> <url-pattern>/getfriends</url-pattern> </servlet-mapping> <servlet-mapping> <servlet-name>GaeDataStoreGetFriendsInfo</servlet-name> <url-pattern>/getfriendsinfo</url-pattern> </servlet-mapping> <servlet-mapping> <servlet-name>GaeDataStoreQuery</servlet-name> <url-pattern>/query</url-pattern> </servlet-mapping> <servlet-mapping> <servlet-name>GaeDataStoreTransaction</servlet-name> <url-pattern>/transaction</url-pattern> </servlet-mapping> <servlet-mapping> <servlet-name>GaeDataStoreCascadeDalete</servlet-name> <url-pattern>/cascadedelete</url-pattern> </servlet-mapping> <welcome-file-list> <welcome-file>index.html</welcome-file> </welcome-file-list> </web-app>
index.html
war/index.htmlは以下となる。
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <!-- The HTML 4.01 Transitional DOCTYPE declaration--> <!-- above set at the top of the file will set --> <!-- the browser's rendering engine into --> <!-- "Quirks Mode". Replacing this declaration --> <!-- with a "Standards Mode" doctype is supported, --> <!-- but may lead to some differences in layout. --> <html> <head> <meta http-equiv="content-type" content="text/html; charset=UTF-8"> <title>GAE:データストアのテスト</title> </head> <body> <h2>データストアの所有関係(1:1)のテスト</h2> <table> <tr> <td><a href="createparent"/>Rootエンティティーをストアします</td> </tr> <tr> <td><a href="createchidren"/>Friends,FriendsInfoエンティティーをストアします</td> </tr> <tr> <td><a href="getfriends"/>Friendsエンティティーをキーを元に取得します</td> </tr> <tr> <td><a href="getfriendsinfo"/>FriendsInfoエンティティーをキーを元に取得します</td> </tr> <tr> <td><a href="query"/>JDOQLでクエリでFriends,FriendsInfoエンティティーを取得します</td> </tr> </table> <br><br> <table> <tr> <td><a href="cascadedelete"/>Friendsエンティティーを全て削除します(カスケード削除)</td> </tr> <tr> <td><a href="transaction"/>トランザクションを使ってFriends,FriendsInfoエンティティーを全て削除します</td> </tr> <tr> <td><a href="deleteparent"/>Rootエンティティーを削除します</td> </tr> </table> </body> </html>
ローカルでの実行とデプロイ
indexを生成するためローカル環境で実行し、war/WEB-INF/appengine-generated/datastore-indexes-auto.xmlを生成する。
その後、GEA/Jにデプロイする。