0

外部で生成されたキー (物理カードから読み取った) を持つ JDO カード エンティティがあります。これは、Card エンティティと同時に作成される User エンティティにリンクします。カードを読み取ってメソッドを呼び出すと、以前に作成したカードとユーザーを返すか、新しいカードを作成するよう AppEngine に要求します。ただし、このメソッドを立て続けに 2 回呼び出すと、最終的に Card エンティティが上書きされ、2 つのユーザー ID が作成されます。

これが私のコードです(ゲッターとセッターを削除しました):

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 が 1 つのエンティティ グループ (rootkey で定義) に含まれており、ルート エンティティにも変更を加えています。これは役に立たないようです。

ヒント、指針はありますか?

4

1 に答える 1

1

go for:getObjectById例外をキャッチします。

getObjectById には強い一貫性があります。つまり、作成直後にオブジェクトが存在する場合は、すぐにオブジェクトを返す必要があります。クエリには結果整合性しかありません。つまり作成後に見つかる可能性がありますが、そうでない可能性もあります。

in case not foundgetObjectByIdは、個別にキャッチして処理できる Entity not found 例外をスローします。

于 2013-01-28T15:43:40.407 に答える