【问题标题】:Generate Automatic Id IdGeneratorStrategy生成自动 ID IdGeneratorStrategy
【发布时间】:2013-02-04 23:09:14
【问题描述】:

我正在使用 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 请求好吗?

提前致谢。

【问题讨论】:

  • 日志说什么? (我也看不懂你上面贴的那些象形文字;我也看不到 Java 持久性代码,比如 pm.makePersistent)。
  • 您可以直接粘贴代码 sn-ps。图片有点小,很难辨认。
  • 我已经通过代码截断更改了图片...抱歉图片不好...
  • 这是我关注的例子youtube.com/watch?v=v9TG7OzsZqQ

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


【解决方案1】:

我认为我已经找到了解决方案。似乎谷歌应用引擎(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 格式)是否具有非空 id 值,甚至在检查对象之前是否已使用此代码存储之前:

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

到目前为止,我还没有看到任何可以为我阐明这方面的文档。我还要补充一点,在试图弄清楚发生了什么之前,我花了很多时间阅读GAE 上的文档。


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

注意:“我所做的这个分叉不应被视为正确答案,它可能会导致您的应用出现意外行为。”

【讨论】:

  • +1 你拯救了我的一天!这可以被认为是 GPE 的错误,它会为 Google Cloud Endpoints 生成不需要的代码。
  • 你好@ToyHunter,我做了一些研究,找到了更好的解决方案。现在我正在使用一个包含一系列键的静态迭代器对象。所以每次我发布一个新实体时,我都会得到新对象的新密钥。我在 Endpoint 类中编写了一个私有静态方法来初始化迭代器,所以当我发布一个新对象时,迭代器得到一个新键,我只是将它分配给新对象并持久化它。这里有一些 reference
  • +1 从人们可能希望通过数据迁移保留 id 的角度来看,您的方法绝对有帮助。只是想知道为什么 App Engine 没有解决所有这些问题。
  • 如果@DataNucleus 能给出他的意见就好了。
【解决方案2】:

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

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

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

【讨论】:

    【解决方案3】:

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

    异常永远不会被捕获,你会得到错误。我不知道这是一个错误还是什么,但是在更新了 catch 语句以捕获两者之后,问题就解决了。

    希望对你有帮助!

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-01-11
      • 2017-08-25
      • 2021-10-30
      • 1970-01-01
      • 2012-04-24
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多