GAE JDO persistence manager GetObjectById返回No such object?(对象不存在?)

3

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

我有这个用户数据管理类,使用singleton 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"是虚拟用户的电子邮件,无论如何。

我如何使用encodedKey通过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;

基于此和谷歌的文档:
应用程序可以使用名称为key的键在保存之前填充此值,也可以将其保留为空。如果编码密钥字段为null,则在保存对象时,该字段将使用系统生成的密钥进行填充。
我认为只需持久化此项即可解决问题:
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客户端提供数据。

2个回答

1

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


1
GAE/J有这样的测试 http://code.google.com/p/datanucleus-appengine/source/browse/trunk/tests/com/google/appengine/datanucleus/test/jdo/HasOneToManySetJDO.java,它被保存在这里http://code.google.com/p/datanucleus-appengine/source/browse/trunk/tests/com/google/appengine/datanucleus/jdo/JDOOneToManyTestCase.java#76,并且它可以正常工作,所以唯一的结论是你没有做它所做的事情。 - DataNucleus

0

我已经注释了@PersistenceCapable,只是上面的代码中没有显示。 - ronnypm

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接