2013-01-24 32 views
0

我有一個帶有外部生成密鑰的JDO卡實體(從物理卡讀取)。這鏈接到一個用戶實體,該實體與卡實體同時創建。當我讀卡並調用方法時,我希望AppEngine將我以前創建的卡和用戶返還給我,或者創建一個新卡。但是,如果我連續兩次調用該方法,則最終將刷新卡實體並創建兩個用戶標識。如何確保Google AppEngine中的新JDO實體在創建之前不存在?

這裏是我的代碼(我已刪除的getter &制定者):

CardEntity.java

@PersistenceCapable public class CardEntity { 

    @PrimaryKey 
    private Key Id; 
    @Persistent 
    @Unowned 
    private UserEntity user; 
} 

UserEntity.java

@PersistenceCapable 
public class CustomerEntity { 

    @PrimaryKey 
    @Persistent(valueStrategy = IdGeneratorStrategy.IDENTITY) 
    private Key key; 
    @Persistent 
    private String name; 
} 

方法從Controller.java

public UserEntity getOrCreateUser(String id) { 
     CardEntity cardEntity; 
     UserEntity userEntity; 
     Query query; 

     PersistenceManager mgr = getPersistenceManager(); 
     Transaction tx = mgr.currentTransaction(); 
     boolean complete = false; 
     while (!complete) { 
      try { 
       tx.begin(); 

       query = mgr.newQuery(CardEntity.class); 
       query.setUnique(true); 
// rootkey is a key for a CardEntity that I am using as the parent for 
// all CardEntities, so they are in the same enitity group, as a hack 
// to try to solve this problem. 
       Key key = KeyFactory.createKey(rootKey, "CardEntity", id); 
       query.setFilter("id == :id"); 
       cardEntity = (CardEntity) query.execute(key); 
       if (CardEntity == null) { 
        cardEntity = new CardEntity(); 
        cardEntity.setId(key); 
        userEntity = new UserEntity(); 
        mgr.makePersistent(userEntity); 
        nfcCardEntity.setUser(UserEntity); 
        mgr.makePersistent(cardEntity); 
        CardEntity rootCardEntity = 
             (CardEntity) mgr.getObjectById(CardEntity.class, rootKey); 
        rootCardEntity.setUser(userEntity); 
// this is another hack to ensure that something changes in this transaction 
// so that if there's a conflict, it will be rolled back 
        mgr.makePersistent(rootCardEntity); 
       } else { 
        userEntity = cardEntity.getUser(); 
       } 
       tx.commit(); 
      } finally { 
       if (tx.isActive()) { 
        tx.rollback(); 
       } else { 
        complete = true; 
       } 
      } 
     } 
     mgr.close(); 
     return userEntity; 
    } 

我已經嘗試了很多事情,但我經常結束創建多個UserEntities。上面的代碼在一個實體組中具有所有CardEntities(由rootkey定義),我甚至還包括對根實體的修改。這似乎沒有幫助。

任何提示,指針?

+0

即時通訊不確定,因爲我總是直接使用數據存儲api,但根據文件爲什麼你沒有做一個getObjectById?如下所述: https://developers.google.com/appengine/docs/java/datastore/jdo/creatinggettinganddeletingdata#Getting_an_Object_By_Key 這是無論如何正確的方式來獲得一個對象的ID,不要做一個查詢 –

+0

因爲當它不存在時,它會引發一個異常,這比查詢更難處理。另外,我認爲這不會解決問題,是嗎? –

+0

這使我想到了你的數據設計,拋出一個EntityNotFound異常在java中是很常見的,它是一個你可以在事務中處理的專用異常,它會解決你的問題,但是回到設計中,你可能應該重新思考你的實體設計,它不會發生,沒有一個給定的關鍵實體 –

回答

1

尋找:getObjectById並發現異常。

getObjectById具有很強的一致性意味着它應該立即返回一個Object,如果它在創建之後就存在。 查詢只有最終一致性,這意味着它可能在創建後發現,也可能不是,也可能是

未找到的情況下getObjectById拋出一個Entity not found異常,它可以單獨捕獲和處理。

+0

這意味着我需要有一個已知的對象的關鍵,而不是依靠查詢。謝謝 - 回到繪圖板有點:-) –

相關問題