3

我一直在尝试让我的 GAE 代码运行。我在使用 encodeKey 检索用户时遇到问题:

我有这个用户数据管理器类,它使用单例 PMF 管理我的所有 CRUD 事务。

我有用户,使用编码的字符串作为我的密钥:

public class Users implements Serializable {
@PrimaryKey
@Persistent(valueStrategy = IdGeneratorStrategy.IDENTITY)
@Extension(vendorName = "datanucleus", key = "gae.encoded-pk", value = "true")
private String encodedKey;
@Persistent
@Extension(vendorName = "datanucleus", key = "gae.pk-id", value = "true")
private Long keyId;
 --- code continues ----

我在 DM 类中有这个 createUser 方法

public static void createUser(Users user) {
    PersistenceManager pm = PMF.get().getPersistenceManager();
    try {
        Key key = KeyFactory.createKey(Users.class.getSimpleName(),
                user.getEmail());
        user.setEncodedKey(KeyFactory.keyToString(key));
        pm.makePersistent(user);
    } catch (Exception e) {
        logger.log(Level.SEVERE, e.toString());
    } finally {
        pm.close();
    }
}

问题在于这段代码要检索:

    public static Users retrieveUser(String encodedKey) {
    PersistenceManager pm = PMF.get().getPersistenceManager();
    Users user = null;
    try {
//          Key key = KeyFactory.createKey(Users.class.getSimpleName(),
//                  user.getEmail());
// I tried recreating the key with user's email, but it does not work either            
        pm.getObjectById(KeyFactory.stringToKey(encodedKey));
    } catch (Exception e) {
        logger.severe(e.toString());
    } finally {
        pm.close();
    }
    return user;
}

它给了我以下错误:

 SEVERE: javax.jdo.JDOObjectNotFoundException: No such object
 FailedObject:Users("t")
 NestedThrowables:org.datanucleus.exceptions.NucleusObjectNotFoundException: No such object

无论如何,“t”是虚拟用户的电子邮件。

如何使用编码密钥获取使用 PMF 的实体?目前,我正在求助于使用电子邮件和查询进行识别,但是按键获取对象应该可以工作。

编辑

我对模型对象进行了以下更改:

@PrimaryKey
@Persistent(valueStrategy = IdGeneratorStrategy.IDENTITY)
@Extension(vendorName = "datanucleus", key = "gae.encoded-pk", value = "true")
private String encodedKey;
@Persistent
@Extension(vendorName="datanucleus", key="gae.pk-name", value="true")
private String keyName;

基于此和谷歌的文档:

应用程序可以在保存之前使用带名称的键填充此值,也可以将其保留为空。如果编码键字段为空,则在保存对象时该字段将填充系统生成的键。

我认为简单地坚持这一点就可以了:

public static void createUser(Users user) {
    PersistenceManager pm = PMF.get().getPersistenceManager();
    try {
        user.setKeyName(user.getEmail()); 
        pm.makePersistent(user);
    } catch (Exception e) {
        logger.log(Level.SEVERE, e.toString());
    } finally {
        pm.close();
    }
}

但是,没有这样的运气,无论我是否先设置键名,它都会给我这个错误:

SEVERE: javax.jdo.JDOFatalUserException: Invalid primary key for entity.Users.  Cannot have a null primary key field if the field is unencoded and of type String.  Please provide a value or, if you want the datastore to generate an id on your behalf, change the type of the field to Long.
NestedThrowables:
org.datanucleus.exceptions.NucleusFatalUserException: Invalid primary key for entity.Users.  Cannot have a null primary key field if the field is unencoded and of type String.  Please provide a value or, if you want the datastore to generate an id on your behalf, change the type of the field to Long.

我不明白,为什么它没有为我的新实体生成新密钥?由于所有这些问题,我正在考虑回到 Key。我认为encodedKey 会更便携,因为我使用GAE 服务器向我的Android 客户端提供数据。

4

2 回答 2

1

当您将该字段标记为生成其值时,调用setEncodedKey () 有什么意义?(使用valueStrategy=IDENTITY)。如果生成了某些东西(当插入数据库时​​,就像那样),那么传递给setEncodedKey的值将被忽略,通过调用pm.getObjectId(obj)可以清楚地看到。

于 2012-10-11T16:53:06.473 回答
0

您需要使用注释来注释您的类@PersistenceCapable。有关更多信息,请查看使用 JDO 定义数据类

于 2012-10-11T16:37:19.543 回答