我有一個帶有外部生成密鑰的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定義),我甚至還包括對根實體的修改。這似乎沒有幫助。
任何提示,指針?
即時通訊不確定,因爲我總是直接使用數據存儲api,但根據文件爲什麼你沒有做一個getObjectById?如下所述: https://developers.google.com/appengine/docs/java/datastore/jdo/creatinggettinganddeletingdata#Getting_an_Object_By_Key 這是無論如何正確的方式來獲得一個對象的ID,不要做一個查詢 –
因爲當它不存在時,它會引發一個異常,這比查詢更難處理。另外,我認爲這不會解決問題,是嗎? –
這使我想到了你的數據設計,拋出一個EntityNotFound異常在java中是很常見的,它是一個你可以在事務中處理的專用異常,它會解決你的問題,但是回到設計中,你可能應該重新思考你的實體設計,它不會發生,沒有一個給定的關鍵實體 –