生成自动Id IdGeneratorStrategy

时间:2013-02-20 02:56:02

标签: java json google-app-engine curl jdo

我正在使用Goole App Engine构建我的REST API,我已经将我的类标记为 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请求好吗?
  3. 提前致谢。

3 个答案:

答案 0 :(得分:8)

我认为我找到了解决方案。似乎Google App Engine(GAE)框架生成的每个端点都有一个简单的方法,可以在每次有人尝试插入或更新时检查一个持久性实例,所以事实是每次我尝试插入一个新的学生使用curl / json而没有为实例指定de new 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格式发送)是否具有非null id值来解决编辑我的端点类的问题,甚至在使用此代码检查对象是否已经存储之前:

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

到目前为止,我还没有看到任何可以为我澄清这方面的文件。另外,我补充说,我花了很多时间阅读GAE上的文档,然后才弄清楚发生了什么。


所有这些让我觉得可能只是GAE文档可能不是最新的,或者我可能没有足够的搜索,所以如果有人知道。请让我知道并增长常识。谢谢@DataNucleus。

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

答案 1 :(得分:1)

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

异常永远不会被捕获并且您收到错误。我不知道如果它是一个错误或什么,但在更新catch语句以捕获两者之后,问题就解决了。

希望它有所帮助!

答案 2 :(得分:0)

正如AlexSanchez的回答所述,生成的端点代码需要在插入新身份时设置主键。

虽然有些人可能会将此视为错误,但其他人可能会将其视为一项功能,因为它需要客户端以某种方式生成密钥(例如,当密钥类型为String时创建随机uuid)。这样,客户端即使在离线状态下也可以创建实体的完整图表,并在线上传到服务器。

(我认为Spine框架就是这个想法的一个例子:http://spinejs.com/。)