7

自動生成されたエンドポイント クラスの使用について混乱しています。生成されたエンドポイントを使用して、新しいオブジェクトをデータストアに挿入したいと考えています。ただし、スローは例外です。

fooEndpoint.insertFoo(foo); // throws null pointer exception 

私のエンティティ クラスは、https://developers.google.com/appengine/docs/java/datastore/jpa/overview のソースにある例と似てい ます。

ここに私のエンティティがあります:

@Entity
public class Foo {
    @Id
    @GeneratedValue(strategy=GenerationType.IDENTITY)
    private Key ID;

スタック トレースは次のとおりです。

java.lang.NullPointerException
at org.datanucleus.api.jpa.JPAEntityManager.find(JPAEntityManager.java:318)
at org.datanucleus.api.jpa.JPAEntityManager.find(JPAEntityManager.java:256)
at com.FooEndpoint.containsFoo(FooEndpoint.java:150)
at com.FooEndpoint.insertFoo(FooEndpoint.java:96)

一方、EntityManager の persist メソッドを使用すると、新しいオブジェクトを挿入できます。これは、データストアに存在するかどうかをチェックしないためです。

classEndpoint 挿入メソッドはオブジェクトを保存し、自動キーを ID フィールドに割り当てる必要があると思います。

または、ID フィールドを初期化する必要があります。

これは、自動生成されたエンドポイント クラスの insertFoo メソッドです。

  /**
 * This inserts a new entity into App Engine datastore. If the entity already
 * exists in the datastore, an exception is thrown.
 * It uses HTTP POST method.
 *
 * @param foo the entity to be inserted.
 * @return The inserted entity.
 */
public Foo insertFoo(Foo foo) {
    EntityManager mgr = getEntityManager();
    try {
        if (containsFoo(foo)) {
            throw new EntityExistsException("Object already exists");
        }
        mgr.persist(foo);
    } finally {
        mgr.close();
    }
    return foo;
}

これがcontainsFooメソッドです

    private boolean containsFoo(Foo foo) {
    EntityManager mgr = getEntityManager();
    boolean contains = true;
    try {
        Foo item = mgr.find(Foo.class, foo.getID());  // exception occurs here
        if (item == null) {
            contains = false;
        }
    } finally {
        mgr.close();
    }
    return contains;
}

foo.getID() が null です。なぜなら、それは新しいオブジェクトです。アプリエンジンがキーを作成することを期待しています。または、明示的にキーを作成する必要がありますか?

Foo クラスの他のフィールドは、String や booleans などの単純な型です。

御時間ありがとうございます。

4

2 に答える 2

8

私はまったく同じ問題を抱えていました。私が取り組んだ方法を紹介します。

元の自動生成されたエンドポイント クラス関連コード:

private boolean containsFoo(Foo foo) {
    EntityManager mgr = getEntityManager(); 
    boolean contains = true;
    try {
        Foo item = mgr.find(Foo.class, foo.getID());
        if (item == null) {
            contains = false;
        }
    } finally {
        mgr.close();
    }
    return contains;
}

関連するコードを変更して、引数として渡されるエンティティ オブジェクトの null チェックを含めました。

private boolean containsFoo(Foo foo) {
    EntityManager mgr = getEntityManager(); 
    boolean contains = true;
    try {
        // If no ID was set, the entity doesn't exist yet.
        if(foo.getID() == null)
            return false;
        Foo item = mgr.find(Foo.class, foo.getID());
        if (item == null) {
            contains = false;
        }
    } finally {
        mgr.close();
    }
    return contains;
}

このようにして、想定どおりに機能しますが、より経験豊富な回答と説明が表示されると確信しています.

于 2013-05-10T01:00:36.803 に答える
2

Eclipseプラグインを使用してクラウドエンドポイントを自動生成した後(「Google>クラウドエンドポイントクラスの生成」を選択して)、まったく同じ問題が発生していました。

あなたのアドバイスに従って、私は追加しました:

if(foo.getID() == null) // foo を独自のオブジェクトの名前に置き換えます return false;

問題は解決しました。

これは非常に頻繁に発生する問題であるに違いないのに、Google が自動生成されたコードをまだ更新していないのはなぜですか?

解決策をありがとう。

于 2014-09-25T07:34:07.850 に答える