1

Java を使用して Google AppEngine 内の Google データストアに複雑なクラス構成を保存することが可能かどうかを尋ねる前に質問しましたが、すべてのクラスを投稿するのが十分に明確ではなく怠惰でしたが、何時間も苦労した後、あきらめ始めました. したがって、ここにコードに関するより詳細な質問があります。

この種のものはうまくいくはずですが、なんらかの理由でうまくいきません。問題は、オブジェクトを保存してデータベース接続を閉じてから再度開くと、そのオブジェクトのデータが空白になることです。オブジェクトはデータベースにあります。そのオブジェクトの ID を選択すると表示されますが、それ以外はすべて空白です。残念ながら、Google には、そのデータベースの内容を確認するためのデータベース ビューアがありません。私は検索して尋ねようとしましたが、運がありませんでした。( 1つあるのですが、私のコンピューターでは動作しません)

コンテンツ

// imports...
@PersistenceCapable(identityType = IdentityType.APPLICATION)
public class Content{

 @PrimaryKey
 @Persistent(valueStrategy = IdGeneratorStrategy.IDENTITY)
 @Extension(vendorName="datanucleus", key="gae.encoded-pk", value="true")
 private String id;

 @Persistent protected String title;
 @Persistent protected String thumbnailURL;
 @Persistent protected List<Rating> ratings;
 @Persistent protected List<Tag> tags;
 @Persistent protected Double price;
 @Persistent protected User owner;

 // constructor and getters+setters
}

コース

// imports...
@PersistenceCapable(identityType = IdentityType.APPLICATION)
public class Course extends Content{

 @Persistent private Video video;
 @Persistent private Document document;
 @Persistent private String notes;
 @Persistent private String summary;

// constructor and getters+setters
    public String toString(){
  return "ID: " + this.getId() + " Title: "+this.getTitle()+", Price: "+this.getPrice()+", No. of Tags: "+this.getTags().size();
 }

}

ビデオ

// imports...
public class Video extends Content {
  @PrimaryKey
  @Persistent(valueStrategy = IdGeneratorStrategy.IDENTITY)
  @Extension(vendorName="datanucleus", key="gae.encoded-pk", value="true")
  String id;

  @Persistent String fileUrl;

  // constructor and getters+setters
}

書類

// imports...
@PersistenceCapable(identityType = IdentityType.APPLICATION)
public class Document extends Content /*AthenaObject*/ {
 @PrimaryKey
 @Persistent(valueStrategy = IdGeneratorStrategy.IDENTITY)
 @Extension(vendorName="datanucleus", key="gae.encoded-pk", value="true") 
 private String id;

 @Persistent private String docUrl;

 // constructor and getters+setters
}

鬼ごっこ

// imports...
@PersistenceCapable(identityType = IdentityType.APPLICATION)
public class Tag{
 @PrimaryKey
 @Persistent(valueStrategy = IdGeneratorStrategy.IDENTITY)
 @Extension(vendorName="datanucleus", key="gae.encoded-pk", value="true")
 private String id;

 @Persistent private String tagText;

 // constructor and getters+setters
}

永続化してデータストアからデータを取得するコード:

public Boolean testCourse(){
 Boolean isSaved = false;
 PersistenceManager pm = PMF.get().getPersistenceManager();
 Course c = new Course();
 try{
  List<Tag> tags = new ArrayList<Tag>();
  tags.add(new Tag("tag1"));
  tags.add(new Tag("tag2"));
  tags.add(new Tag("tag3"));


  c.setTitle("Course Title - " + new Date().getTime());
  c.setPrice(99.90);
  c.setTags(tags);

  System.out.println(c.toString()); // **Output:** ID: null Title: Course Title - 1247116147858, Price: 99.9, No. of Tags: 3
  pm.makePersistent(c);

  Course cAfter = pm.getObjectById(Course.class, KeyFactory.stringToKey(c.getId()));
  System.out.println(cAfter.toString()); // **Output:** agptYRtzaWL4gZDb3Vy4ErYFgw Title: Course Title - 1247116147858, Price: 99.9, No. of Tags: 3
  isSaved = true;
 }
 catch(Exception e){
  e.printStackTrace();
  isSaved = false;
 }
 finally{
  pm.close();
 }


 pm = PMF.get().getPersistenceManager();

 try{

  Course cAfterClose = pm.getObjectById(Course.class, KeyFactory.stringToKey(c.getId()));
  System.out.println(cAfterClose.toString()); // **Error**: See below
 }
 catch(Exception e){e.printStackTrace();}
 finally{pm.close();}


 return isSaved;
}

出力は次のとおりです。

ID: nullTitle: コース タイトル - 1247117389679、価格: 99.9、タグ数: 3 ID: agptYWtzaW1zYXBwcgwLEgZDb3Vyc2UYGAwTitle: コース タイトル - 1247117389679、価格: 99.9、タグ数: 3 java.lang.NullPointerException at com.athena.server. entity.Course.toString(Course.java:94) at com.athena.server.CourseServiceImpl.testCourse(CourseServiceImpl.java:146) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke( NativeMethodAccessorImpl.java:39) の sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) の java.lang.reflect.Method.invoke(Method.java:585) の com.google.gwt.user.server.rpc .RPC.invokeAndEncodeResponse(RPC.java:527) com.google.gwt.user.server.rpc.RemoteServiceServlet.processCall(RemoteServiceServlet.java:166) com.google.gwt.user.server.rpc.RemoteServiceServlet.doPost(RemoteServiceServlet.java:86) で javax.servlet.http.HttpServlet.service(HttpServlet.java:713) で javax.servlet.http.HttpServlet .service(HttpServlet.java:806) at org.mortbay.jetty.servlet.ServletHolder.handle(ServletHolder.java:487) at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1093) at com.google.apphosting.utils.servlet.TransactionCleanupFilter.doFilter(TransactionCleanupFilter.java:43) org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1084) at org.mortbay.jetty.servlet. org.mortbay.jetty.servlet.SessionHandler.handle(SessionHandler.java:181) org.mortbay.jetty.handler.ContextHandler.handle(ContextHandler.java:712) で org.mortbay.jetty.webapp.WebAppContext.handle(WebAppContext.java:405) で com.google.apphosting.utils で.jetty.DevAppEngineWebAppContext.handle(DevAppEngineWebAppContext.java:54) org.mortbay.jetty.handler.HandlerWrapper.handle(HandlerWrapper.java:139) com.google.appengine.tools.development.JettyContainerService$ApiProxyHandler.handle(JettyContainerService) .java:306) org.mortbay.jetty.handler.HandlerWrapper.handle(HandlerWrapper.java:139) で org.mortbay.jetty.Server.handle(Server.java:313) で org.mortbay.jetty.HttpConnection. org.mortbay.jetty.HttpConnection$RequestHandler.content(HttpConnection.java:844) の handleRequest(HttpConnection.java:506) org.mortbay.jetty.HttpParser.parseNext(HttpParser.java:644) org.mortbay.jetty.HttpParser.parseAvailable(HttpParser.java:211) で org.mortbay.jetty.HttpConnection.handle(HttpConnection.java:381) で org.mortbay.io.nio.SelectChannelEndPoint.run(SelectChannelEndPoint) .java:396) org.mortbay.thread.BoundedThreadPool$PoolThread.run(BoundedThreadPool.java:442) で

このエラーは、文字列が null であることを意味します。しかし、レコードはデータベースにあります。そして、それは永続的でなければなりません。データが空白なのはなぜですか???

なぜこれが私に起こっているのですか?

4

2 に答える 2

1

エラーの原因は正確にはわかりませんが、トラブルシューティングに役立ついくつかの手順を以下に示します。

まず、問題をできるだけ小さなテスト ケースに絞り込みます。上記のクラスがたくさんありますが、この問題はそのうちの 2 つまたは 3 つだけで重複する可能性があります。

次に、エンティティがデータストアでどのように見えるかを正確に確認したい場合は、次のようにする必要があります (または、アプリを appengine にアップロードしてそこで実行し、データビューアーを使用することもできます)。

Query q = pm.newQuery(Course.class);
List<Course> list = (List<Course>) q.execute();
for(Course c: list){
  System.out.println("Course id:" + c.getId());
  System.out.println("Course title:" + c.getTitle());
  //...
}
于 2009-07-09T19:12:09.290 に答える
0

私は、所有されていない 1 対多の関係を使用して最も幸運に恵まれました。基本的に、リストはキー オブジェクトのセットに置き換えられます。

http://code.google.com/appengine/docs/java/datastore/relationships.html

于 2009-07-15T18:54:11.120 に答える