Exception: Query result sets are not modifiable ここで同様の問題を見ましたが、質問に答えなかったので、新しい質問を開始することにしました。
一時的に保存することにより、Google App Engine の高レプリケーション データストアを使用して一貫性のない読み取りの問題 ( https://groups.google.com/forum/?fromgroups=#!topic/google-appengine/E95wH0RkJUE ) を回避しようとしています。静的変数に最後に追加されたオブジェクト。
ユーザーが新しいフライトを追加するたびに、新しいフライト オブジェクトを直接永続化するのではなく、静的変数として PMF に保存します。
したがって、フライトのリストがクエリで取得されると、結果がリストに格納され、リストが最後に追加されたオブジェクトと比較されます。最後に追加されたオブジェクトがリストにない場合は、最後に追加されたオブジェクトを手動で追加しますリスト。
ただし、この方法を使用すると、新しく追加されたオブジェクトがリストにない場合は常に次の例外が発生し、手動で追加します。
Oct 6, 2012 2:19:38 PM com.google.apphosting.utils.jetty.JettyLogger warn
WARNING: /
java.lang.UnsupportedOperationException: Query result sets are not modifiable
at org.datanucleus.store.query.AbstractQueryResult.add(AbstractQueryResult.java:222)
at com.jimfoo88.helloorm.GetFlights.queryJDO(GetFlights.java:101)
at com.jimfoo88.helloorm.GetFlights.doGet(GetFlights.java:50)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:617)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:717)
at org.mortbay.jetty.servlet.ServletHolder.handle(ServletHolder.java:511)
at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1166)
at com.google.appengine.tools.development.HeaderVerificationFilter.doFilter(HeaderVerificationFilter.java:35)
at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1157)
at com.google.appengine.api.blobstore.dev.ServeBlobFilter.doFilter(ServeBlobFilter.java:60)
at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1157)
at com.google.apphosting.utils.servlet.TransactionCleanupFilter.doFilter(TransactionCleanupFilter.java:43)
at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1157)
at com.google.appengine.tools.development.StaticFileFilter.doFilter(StaticFileFilter.java:125)
at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1157)
at com.google.appengine.tools.development.BackendServersFilter.doFilter(BackendServersFilter.java:97)
at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1157)
at org.mortbay.jetty.servlet.ServletHandler.handle(ServletHandler.java:388)
at org.mortbay.jetty.security.SecurityHandler.handle(SecurityHandler.java:216)
at org.mortbay.jetty.servlet.SessionHandler.handle(SessionHandler.java:182)
at org.mortbay.jetty.handler.ContextHandler.handle(ContextHandler.java:765)
at org.mortbay.jetty.webapp.WebAppContext.handle(WebAppContext.java:418)
at com.google.appengine.tools.development.DevAppEngineWebAppContext.handle(DevAppEngineWebAppContext.java:94)
at org.mortbay.jetty.handler.HandlerWrapper.handle(HandlerWrapper.java:152)
at com.google.appengine.tools.development.JettyContainerService$ApiProxyHandler.handle(JettyContainerService.java:370)
at org.mortbay.jetty.handler.HandlerWrapper.handle(HandlerWrapper.java:152)
at org.mortbay.jetty.Server.handle(Server.java:326)
at org.mortbay.jetty.HttpConnection.handleRequest(HttpConnection.java:542)
at org.mortbay.jetty.HttpConnection$RequestHandler.headerComplete(HttpConnection.java:923)
at org.mortbay.jetty.HttpParser.parseNext(HttpParser.java:547)
at org.mortbay.jetty.HttpParser.parseAvailable(HttpParser.java:212)
at org.mortbay.jetty.HttpConnection.handle(HttpConnection.java:404)
at org.mortbay.io.nio.SelectChannelEndPoint.run(SelectChannelEndPoint.java:409)
at org.mortbay.thread.QueuedThreadPool$PoolThread.run(QueuedThreadPool.java:582)
以下の私のコードは、Google アプリ エンジンのサンプル、HelloORM http://code.google.com/p/datanucleus-appengine/source/browse/trunk/demos/helloorm/src/com/google/appengine/demos/helloormに基づいています。 /GetFlights.java?r=736
読みやすくするために変更した部分のみを示します。
AddFlight.java
private void doPostJDO(Flight f) {
PersistenceManager pm = PMF.get().getPersistenceManager();
PMF.setLastObjectAdded(f);
try {
pm.makePersistent(f);
} finally {
pm.close();
}
}
PMF.java
// Copyright 2008 Google Inc. All Rights Reserved.
package com.jimfoo88.helloorm;
import javax.jdo.JDOHelper;
import javax.jdo.PersistenceManagerFactory;
/**
* @author Max Ross <maxr@google.com>
*/
public final class PMF {
private static Object lastObjectAdded;
private static final PersistenceManagerFactory INSTANCE = JDOHelper.getPersistenceManagerFactory("transactions-optional");
public static Object getLastObjectAdded() {
return lastObjectAdded;
}
public static void setLastObjectAdded(Object lastObject) {
lastObjectAdded = lastObject;
}
public static PersistenceManagerFactory get() {
return INSTANCE;
}
private PMF() {}
}
GetFlights.java
private Collection<Flight> queryJDO(String query) {
PersistenceManager pm = PMF.get().getPersistenceManager();
try {
List<Flight> flights = (List<Flight>) pm.newQuery(query).execute();
// Force all results to be pulled back before we close the entity
// manager.
// We could have also called pm.detachCopyAll()
flights.size();
//pm.detachCopyAll(flights);
boolean found = false;
try {
for (Flight f : flights) {
if ((Flight) PMF.getLastObjectAdded() == null) {
found = true;
break;
}
if (f.getDest() == ((Flight) PMF.getLastObjectAdded())
.getDest()
&& f.getOrig() == ((Flight) PMF
.getLastObjectAdded()).getOrig()) {
logger.info("found object " + f.toString()
+ "in datastore");
found = true;
break;
}
}
if (found == false) {
logger.info("did not find object "
+ (Flight) PMF.getLastObjectAdded()
+ " in datastore, need to add it");
flights.add((Flight) PMF.getLastObjectAdded());
}
} catch (NullPointerException e) {
logger.error(e.getMessage());
}
return flights;
} finally {
pm.close();
}
}
誰かが私の間違いを指摘していただければ幸いです。この問題を回避するためのより良い方法があれば、お知らせください。ありがとう。