2013-02-20 123 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語句來捕獲兩者之後,問題就解決了。

希望它能幫助!