Google Datastore - Problems updating entity

2019-05-12 18:04发布

I am dusting off my google app-engine / datastore skills ... and getting stuck on something very simple.

As per the example on the GAE documentation I am trying to update an entity as follows:

// persistence and business logic
PersistenceManager pm = PMF.get().getPersistenceManager();

// get it
NickName n = pm.getObjectById(NickName.class, nicknameId);

// update fields
n.givenName = "new name";
n.nickName = "new nickname";
n.timeStamp = new Date();               

// close manager to persist changes
pm.close();

This doesn't work (as in the changes are not persisted, but no errors or anything else)!

At the same time I found that if I create a new entity with the same ID the changes get persisted:

// persistence and business logic
PersistenceManager pm = PMF.get().getPersistenceManager();

NickName n = new NickName("new name", "new nickname", new Date());

// set id
n.id = nicknameId;

pm.makePersistent(n);

pm.close();

I have the feeling I already solved this the 1st time I approached app engine and the data-store.

This is what my entity looks like:

@PersistenceCapable
public class NickName {

    public NickName(String name, String nickname, Date timestamp) {
        this.givenName = name;
        this.nickName = nickname;
        this.timeStamp = timestamp;
    }

    @PrimaryKey
    @Persistent(valueStrategy = IdGeneratorStrategy.IDENTITY)
    public String id;

    @Persistent
    public String givenName;

    @Persistent
    public String nickName;

    @Persistent
    public Date timeStamp;
}

Any help appreciated!

1条回答
兄弟一词,经得起流年.
2楼-- · 2019-05-12 18:49

One issue may be that you are setting the fields directly instead of going through the setter methods. I'm fairly certain that JDO works by instrumenting the field setters so that they notify the persistence layer of any changes that occur. It has no way of directly monitoring changes to the backing field values themselves. So maybe try:

n.setGivenName("new name");
n.setNickName("new nickname");
n.setTimeStamp(new Date()); 

You're able to get away with setting the field directly when you create the object because the makePersistent() call tells the persistence manager that is needs to inspect the field values and save them. Though it's worth noting that setting field values directly like this is generally considered to be poor coding style.

Also, have you tried using the JPA interface instead of the JDO interface? In GAE they should be interchangeable:

EntityManager em = EMF.get();

NickName n = em.find(NickName.class, nicknameId);

n.givenName = "new name";
n.nickName = "new nickname";
n.timeStamp = new Date();    

em.merge(n);

em.close();

This gives you an explicit merge() call which should work even with setting the field values directly.

查看更多
登录 后发表回答