2013-02-20 89 views
8

我使用Goole的App Engine的建立我的REST API,我已经打上我的班级为PersistenceCapable也是我得到了我的定义@PrimaryKey 也被标记为@Persistent(valueStrategy = IdGeneratorStrategy.IDENTITY),我也已经生成了EndPoints。但是当我在终端窗口中输入一个curl命令来插入一个新的实体或注册表时,它不起作用。这是代码:生成自动ID IdGeneratorStrategy

@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请求好吗?

在此先感谢。

+0

和日志说什么? (我也读不出你上面发布的那些象形文字;我也没有看到Java持久代码,就像pm.makePersistent一样)。 – DataNucleus 2013-02-20 05:35:33

+0

你可以直接粘贴代码片段。图片有点小,很难弄清楚。 – 2013-02-20 09:34:59

+0

我已经改由代码图像剪断......对形象不好对不起...... – AlexSanchez 2013-02-21 00:32:05

回答

8

我认为我找到了解决方案。似乎Google App Engine(GAE)框架生成的每个端点都有一个简单的方法,可以在每次有人试图插入或更新以及持久实例时进行检查,所以事实上每当我尝试插入新的学生使用curl/JSON没有指定日为实例新的ID它显示类似这样的错误消息:

"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格式)在检查对象之前是否已经存储该代码之前具有非空id值:

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

到目前为止,我还没有看到任何文件,可以为我澄清这方面。另外我还补充说,在试图找出发生的事情之前,我花了很多时间阅读GAE上的文档。


所有这一切让我觉得,也许只是也许在GAE文档是不是最新的或可能是我还没有足够的搜索,所以如果有人知道。请让我知道它并发展常识。谢谢@DataNucleus。

注意:“我所做的这个分支不应被视为正确的答案,它可能会带你到你的应用的意外行为。”

+1

+1您的例子拯救了我的一天!这可以被视为GPE的一个错误,它会为Google Cloud Endpoints生成不需要的代码。 – 2013-04-29 17:29:57

+2

你好@ToyHunter,我做了一些研究,我找到了一个更好的解决方案。现在我正在使用一个包含一系列键的静态Iterator对象。所以每次我发布一个新实体时,我都会为新对象获取新密钥。我在初始化迭代器的Endpoint类中编写了一个私有静态方法,所以当我POST一个新对象时,迭代器会得到一个新的键,我只是将它分配给新对象并保留它。在这里有一些[引用](https:/ /developers.google.com/appengine/docs/java/javadoc/com/google/appengine/api/datastore/KeyRange) – AlexSanchez 2013-04-30 01:03:44

+1

+1你的做法是从那些可能希望保留通过数据迁移IDS的角度肯定是有帮助的。只是想知道为什么所有这些问题都不被App Engine照顾。 – 2013-04-30 04:26:06

0

正如AlexSanchez的回答中所述,生成的端点代码期望在插入新身份时已经设置了主键。

虽然有些人可能认为这是一个错误,其他人可能查看作为特征,因为它需要在客户端以某种方式生成密钥(例如,通过当密钥类型是字符串创建一个随机UUID)。这样,即使在离线状态下,客户端也可以创建完整的实体图,并在线上将其上传到服务器。

(我觉得脊柱框架是这样的想法一个例子:http://spinejs.com/

1

的问题在于包含自动生成的端点的方法。抛出的异常是当id为null并且该方法捕获异常javax.jdo.JDOObjectNotFoundException时,javax.jdo.JDOFatalInternalException。

唯一的例外是没有抓到,你会得到错误。如果这是一个错误或者是什么,我不会这样做,但是在更新catch语句来捕获两者之后,问题就解决了。

希望它能帮助!