2012年8月26日日曜日

[AppEngine] JDO でデータストアを使う

前回、PersistenceManagerFactory と データクラス が準備できたので、 作成・削除・更新操作・取得をやってみる。
各操作は、PersistenceManagerFactory から取得した PersistenceManagerに対して実行する。
  • 取得
    キー値で取得する際には、PersistenceManager#getObjectById が使える。
    それ以外に検索条件などで取得する際には、Query オブジェクトを使用する。
    Query query = pm.newQuery(MyData.class);
    @SuppressWarnings("unchecked") 
    List result = (List)query.execute();
    
  • 作成
    データオブジェクトを作成してプロパティをセットした後、 PersistenceManager#makePersistent を実行する。
    MyData data = new MyData();
    data.setName(req.getParameter("name"));
    pm.makePersistent(data);
    
  • 削除
    データオブジェクトを取得してプロパティをセットした後、 PersistenceManager#deletePersistent を実行する。
    Long id = 削除対象のID;
    MyData data = pm.getObjectById(MyData.class, id);
    pm.deletePersistent(data);
    
  • 更新
    データオブジェクトを取得して新しいプロパティをセットする。 データストア内の値の更新は PersistenceManager をclose したときに自動的に行われる。
    Long id = 更新対象のID;
    String name = 新しい値;
    MyData data = pm.getObjectById(MyData.class, id);
    data.setName(name);
    ...
    pm.close();
    




試してみたコードは以下の通り:

JdoSampleServlet.java:

@SuppressWarnings("serial")
public class JdoSampleServlet extends HttpServlet {
    public void doGet(HttpServletRequest req, HttpServletResponse resp)
            throws IOException, ServletException {
        execute(req);
        readData(req);
        RequestDispatcher rd = getServletContext().getRequestDispatcher(
                "/jsp/JdoSample.jsp");
        rd.forward(req, resp);
    }
    
    public void execute(HttpServletRequest req) throws IOException {
        PersistenceManager pm = PMF.get().getPersistenceManager();
        try {
            final String operation = req.getParameter("operation");
            if ("add".equals(operation)) {
                MyData data = new MyData();
                data.setName(req.getParameter("name"));
                pm.makePersistent(data);
            } else if ("delete".equals(operation)) {
                String id = req.getParameter("id");
                MyData data = pm.getObjectById(MyData.class, Long.valueOf(id));
                pm.deletePersistent(data);
            } else if ("update".equals(operation)) {
                String id = req.getParameter("id");
                String name = req.getParameter("name");
                MyData data = pm.getObjectById(MyData.class, Long.valueOf(id));
                data.setName(name);
            }
        } finally {
            if ( pm !=null && ! pm.isClosed()) {
                pm.close();
            };
        }
    }

    public void readData(HttpServletRequest req) throws IOException {
        PersistenceManager pm = PMF.get().getPersistenceManager();
        try {
            Query query = pm.newQuery(MyData.class);
            @SuppressWarnings("unchecked") 
            List<MyData> dataList = (List<MyData>)query.execute();
            pm.detachCopyAll(dataList);
            req.setAttribute("dataList", dataList);
        } finally {
            if ( pm !=null && ! pm.isClosed()) {
                pm.close();
            };
        }
    }

JdoSample.jsp:

<%@ page import="java.util.*" contentType="text/html; charset=utf-8" %>
<%@ page import="xawa99.test.HelloApp.MyData" %>
<html><body>
 
<table frame="box" rules="all">
<thead><tr><td> id </td><td> name </td></tr></thead>
<tbody>
List<MyData> dataList = (List<MyData>)request.getAttribute("dataList");
for (MyData data : dataList) { 
%>
<tr><td><%= data.getId()%></td><td><%= data.getName() %></td></tr>
 <% } %>
</tbody></table>
<hr />
<a href="jdosample">view</a><br /><br />
<form submit="jdosample" method="GET">
name: <input type="text" name="name" />
<input type="hidden" name="operation" value="add" />
<input type="submit" value="ADD" />
</form>
<form submit="jdosample" method="GET">
id: <input type="text" name="id" /> 
<input type="hidden" name="operation" value="delete" />
<input type="submit" value="DELETE" />
</form>
<form submit="jdosample" method="GET">
id: <input type="text" name="id" />
name: <input type="text" name="name" />
<input type="hidden" name="operation" value="update">
<input type="submit" value="UPDATE">
</form>
</body></html>

更新操作では結果取得前にいったん PersistenceManager をクローズして更新を反映させる必要があるので、書き込み系とそのあとの取得系では使用する PersistenceManager を別にしている。

また、Query#execute で取得したリストはまだ実際にはフェッチされていないので、 値を取得する前に PersistenceManager がクローズされてしまうとエラーになる。

org.datanucleus.exceptions.NucleusUserException: 
Object Manager has been closed

それを防ぐために、PersistenceManager.detachCopyAll を実行してあらかじめフェッチさせる必要がある。



0 件のコメント:

コメントを投稿