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 持久方法时,我可以插入新对象。因为,这不会检查数据存储上是否存在。

我希望,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() 为空。因为,它是新对象。我期待着,应用引擎会为它创建一个密钥。或者我需要为它显式创建一个密钥?

Foo 类中的其他字段是简单类型,例如字符串和布尔值。

谢谢你的时间。

4

2 回答 2

8

我有完全相同的问题。我将介绍我解决它的方法。

原始自动生成的 Endpoints 类相关代码:

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;
}

更改了相关代码以包括对作为参数传递的实体对象的空检查。

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 Plugin 自动生成云端点(通过选择“Google > Generate Cloud Endpoint Class”)后,我遇到了同样的问题。

根据您的建议,我补充说:

if(foo.getID() == null) // 将 foo 替换为你自己的对象名 return false;

问题解决了。

谷歌怎么还没有更新自动生成的代码,因为这一定是一个反复出现的问题?

感谢您的解决方案。

于 2014-09-25T07:34:07.850 回答