8

Goole AppEngineを使用してRESTAPIを構築しています。クラスをPersistenceCapableとしてマークし、 @ PrimaryKeyを定義し、@ Persistent (valueStrategy = IdGeneratorStrategy.IDENTITY)としてマークしました。また、すでにEndPointsを使用しています。生成されます。しかし、ターミナルウィンドウにcurlコマンドを入力して新しいエンティティまたはレジストリを挿入すると、機能しません。これはコードです:

 @PersistenceCapable(identityType = IdentityType.APPLICATION)
 class Student{
    @PrimaryKey
    @Persistent(valueStrategy = IdGeneratorStrategy.IDENTITY)
    private Long     id;
    private String   studentName;
    ....
    ....
    ....
}

これは私のローカルサーバーからのcurlコマンドと応答です。新しいエンティティを挿入しようとすると

curl -H 'Content-Type: application/json' -d'{"studentName": "myname"}' htto://localhost:8889/_ah/api/utp/v1/student

これはローカルサーバーからの応答です。

"error" : {
"message" : "javax.jdo.JDOFatalInternalException: El valor de llave dado para construir una identidad de SingleFieldIdentity de tipo \"class javax.jdo.identity.LongIdentity\" para la clase \"class com.alex.wserver.Student\" es nulo.\nNestedThrowables:\norg.datanucleus.exceptions.NucleusException: El valor de llave dado para construir una identidad de SingleFieldIdentity de tipo \"class javax.jdo.identity.LongIdentity\" para la clase \"class com.alex.wserver.Student\" es nulo."

私はidが自動的に生成されて挿入されたと思っていました。しかし、それはここでは起こっていません。IDを一緒に挿入するのとは異なり


  1. 私のクラスは間違っていますか?
  2. POST / jsonリクエストは大丈夫ですか?

前もって感謝します。

4

3 に答える 3

8

私は解決策を見つけたと思います。Google App Engine(GAE)フレームワークによって生成されたすべてのエンドポイントには、誰かが挿入または更新しようとするたびに永続的なインスタンスをチェックする簡単な方法があるようです。インスタンスの新しい ID を指定せずに curl/json を使用している学生は、次のようなエラー メッセージを表示しました。

    "error": {
      "message": javax.jdo.JDOFatalInternalException: The key value passed to construct a
      SingleFieldIdentity type \ class javax.jdo.identity.LongIdentity \ for class \ class com.alex.wserver.Student \ is null. \ nNestedThrowables: \ norg.datanucleus.exceptions.NucleusException: the key value passed to construct a SingleFieldIdentity type \ class javax.jdo.identity.LongIdentity \ for class \ class com.alex . wserver.Student \ is null.

そのため、新しいオブジェクト (curl コマンドとラップされた json 形式によって送信された) に null 以外の id 値があるかどうかを確認してから、オブジェクトが以前に保存されているかどうかを確認することで、エンドポイント クラスの編集の問題を解決しました。

        if(student.getKey() != null){
            if (containsStudent(student)) {
                throw new EntityExistsException("Object already exists");
            }
        }
        mgr.makePersistent(student);

これまでのところ、その側面を明確にすることができるドキュメントは見たことがありません。また、何が起こっているのかを把握する前に、 GAEに関するドキュメントを読むのに多くの時間を費やしてきました。


おそらくGAEのドキュメントが最新ではないか、十分に検索していないのではないかと思いました。私にそれを知らせて、共通の知識を育ててください。ありがとう@DataNucleus。

注:「私が作成したこのフォークは、正解と見なされるべきではありません。アプリの予期しない動作が発生する可能性があります。」

于 2013-02-22T00:12:55.003 に答える
0

AlexSanchez による回答で指摘されているように、生成されたエンドポイント コードは、新しい ID の挿入時に主キーが既に設定されていることを想定しています。

これをバグと見なす人もいれば、機能と見なす人もいます。これは、クライアントが何らかの方法でキーを生成する必要があるためです (たとえば、キーの種類が文字列の場合にランダムな uuid を作成するなど)。このようにして、クライアントはオフラインでもエンティティの完全なグラフを作成し、オンラインになったらそれらをサーバーにアップロードできます。

(Spine フレームワークはこのアイデアの例だと思います: http://spinejs.com/。)

于 2013-05-26T12:00:14.803 に答える