更新GAE中的对象 [英] Updating objects in GAE

查看:61
本文介绍了更新GAE中的对象的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个问题,我无法解决。我试图在网上搜索解决方案,但是我没有找到任何通用解决方案。我想在数据存储中更新一个对象,无论它是什么类。为此,这里是我用于该项目的代码



我使用的是DataNucleus和Google AppEngine。



这里是我的jdoconfig.xml

 <?xml version =1.0encoding =utf-8?> 
< jdoconfig xmlns =http://java.sun.com/xml/ns/jdo/jdoconfig
xmlns:xsi =http://www.w3.org/2001/XMLSchema -instance
xsi:noNamespaceSchemaLocation =http://java.sun.com/xml/ns/jdo/jdoconfig>

< persistence-manager-factory name =transactions-optional>
< property name =javax.jdo.PersistenceManagerFactoryClass
value =org.datanucleus.store.appengine.jdo.DatastoreJDOPersistenceManagerFactory/>
< property name =javax.jdo.option.ConnectionURLvalue =appengine/>
< property name =javax.jdo.option.NontransactionalReadvalue =true/>
< property name =javax.jdo.option.NontransactionalWritevalue =true/>
< property name =javax.jdo.option.RetainValuesvalue =true/>
< property name =datanucleus.appengine.autoCreateDatastoreTxnsvalue =true/>
< / persistence-manager-factory>
< / jdoconfig>

My PMF class

  public final class PMF {
private static final PersistenceManagerFactory pmfInstance =
JDOHelper.getPersistenceManagerFactory(transactions-optional);

private PMF(){}

public static PersistenceManagerFactory get(){
return pmfInstance;


public static PersistenceManager getPersistenceManager(){
return pmfInstance.getPersistenceManager();




$ b我的BaseModel类是所有类的超类项目模型

pre $ lt; code> @Inheritance(strategy = InheritanceStrategy.SUBCLASS_TABLE)
@PersistenceCapable(detachable =true, identityType = IdentityType.APPLICATION)
公共抽象类BaseModel实现Serializable {

@PrimaryKey
@Persistent(valueStrategy = IdGeneratorStrategy.IDENTITY)
protected Key id;

public boolean equals(Object obj){
try {
return obj instanceof BaseModel? this.getId()。getId()==((BaseModel)obj).getId()。getId():false;
} catch(Exception e){
return false;





这里是类( $ @PersistenceCapable(detachable =true,code> Project )我要保存

identityType = IdentityType.APPLICATION)
public class Project extends BaseModel implements BeanModelTag {

private static final long serialVersionUID = 3318013676594981107L;

@Persistent
私人字符串名称;

@Persistent
私有字符串描述;

@Persistent
私人日期截止日期;

@Persistent
私有整数状态;

@Persistent
私钥管理器;

@Persistent
private Set< Key>球队;
}

为此,我尝试了几件事情。下面的这个方法保存了一个成功的Project实例,但是当我打电话去更新一个已经分离的对象时,只有字段截止时间被更新,其他属性没有更新(但是,I进入调试模式检查其他属性是否发生了变化,是的,但是只保存截止日期)。

  public void save(BaseModel object){
PersistenceManager pm = PMF.getPersistenceManager();
尝试{
pm.makePersistent(object);
} finally {
pm.close();


$ / code>

所以,我试了下面的代码

  public void update(Project object){
PersistenceManager pm = PMF.get()。getPersistenceManager();
try {
pm.currentTransaction()。begin();

Project p = pm.getObjectById(Project.class,object.getId());
p.setName(object.getName());
p.setDeadline(object.getDeadline());
p.setDescription(object.getDescription());
p.setTeam(p.getTeam());
p.setStatus(object.getStatus());

pm.currentTransaction()。commit();
} catch(Exception e){
e.printStackTrace();
pm.currentTransaction()。rollback();
} finally {
pm.close();
}
}

它起作用了。好吧,它的工作方式是这样的,但我需要一个通用的方法来处理所有的模型,所以我试过了这个方法。

  public void update (BaseModel对象){
PersistenceManager pm = PMF.get()。getPersistenceManager();
try {
pm.currentTransaction()。begin();

BaseModel ob = pm.getObjectById(object.getClass(),object.getId());

(Field f:ob.getClass()。getDeclaredFields()){
if(!f.toString()。contains(final)){
f .setAccessible(真);
for(Field g:object.getClass()。getDeclaredFields()){
g.setAccessible(true);
if(f.getName()。equals(g.getName())){
f.set(ob,g.get(object));
}
g.setAccessible(false);
}
}
f.setAccessible(false);
}

pm.makePersistent(ob);
pm.currentTransaction()。commit();
} catch(Exception e){
e.printStackTrace();
pm.currentTransaction()。rollback();
} finally {
pm.close();






$ b

但它根本不起作用,保存,但是当我手动System.out属性时,它们被改变了。我尝试过,没有 pm.makePersistent(ob); ,但没有运气。我不知道该怎么办。我在这个项目中有120个模型继承自 BaseModel ,我无法找到一种方法来进行适用于我的模型的更新。



-----------编辑-----------



感谢您的回答。这是我现在的解决方案。

  public void update(BaseModel object){
PersistenceManager pm = 。PMF.get()getPersistenceManager();
try {
pm.currentTransaction()。begin();

BaseModel ob = pm.getObjectById(object.getClass(),object.getId());

for(Field f:ob.getClass()。getDeclaredFields()){
if(!Pattern.compile(\\bfinal\\b).matcher (f.toString())。find()){
f.setAccessible(true);
for(Field g:object.getClass()。getDeclaredFields()){
g.setAccessible(true);
if(f.getName()。equals(g.getName())){
f.set(ob,g.get(object));
JDOHelper.makeDirty(ob,f.getName());
}
g.setAccessible(false);
}
f.setAccessible(false);
}
}

pm.makePersistent(object);
pm.currentTransaction()。commit();
} catch(Exception e){
e.printStackTrace();
pm.currentTransaction()。rollback();
} finally {
pm.close();
}
}


解决方案

使用JDO字节码增强方法不会检测到更新字段的反射。如果你想直接更新字段(无论是通过字段还是反射),那么你可以调用

  JDOHelper.makeDirty(obj, myFieldName); 

完成更新后,更改将由JDO注册并因此在数据存储区中更新。

I have a problem that I can't be able to solve. I've tried to search on the web for solutions, but I didn't find any generic solution. I want to update an object, whatever it's class may be, in the datastore. For that, here's the code I'm using for the project

I'm using DataNucleus and Google AppEngine.

Here's my jdoconfig.xml

<?xml version="1.0" encoding="utf-8"?>
<jdoconfig xmlns="http://java.sun.com/xml/ns/jdo/jdoconfig"
   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xsi:noNamespaceSchemaLocation="http://java.sun.com/xml/ns/jdo/jdoconfig">

   <persistence-manager-factory name="transactions-optional">
       <property name="javax.jdo.PersistenceManagerFactoryClass"
           value="org.datanucleus.store.appengine.jdo.DatastoreJDOPersistenceManagerFactory"/>
       <property name="javax.jdo.option.ConnectionURL" value="appengine"/>
       <property name="javax.jdo.option.NontransactionalRead" value="true"/>
       <property name="javax.jdo.option.NontransactionalWrite" value="true"/>
       <property name="javax.jdo.option.RetainValues" value="true"/>
       <property name="datanucleus.appengine.autoCreateDatastoreTxns" value="true"/>
   </persistence-manager-factory>
</jdoconfig>

My PMF class

public final class PMF {
    private static final PersistenceManagerFactory pmfInstance =
        JDOHelper.getPersistenceManagerFactory("transactions-optional");

    private PMF() {}

    public static PersistenceManagerFactory get() {
        return pmfInstance;
    }

    public static PersistenceManager getPersistenceManager() {
        return pmfInstance.getPersistenceManager();
    }
}

My BaseModel class, wich is a superclass for all the models of the project

@Inheritance(strategy = InheritanceStrategy.SUBCLASS_TABLE)
@PersistenceCapable(detachable = "true", identityType = IdentityType.APPLICATION)
public abstract class BaseModel implements Serializable {

    @PrimaryKey
    @Persistent(valueStrategy = IdGeneratorStrategy.IDENTITY)
    protected Key id;

    public boolean equals(Object obj) {
        try {
            return obj instanceof BaseModel ? this.getId().getId() == ((BaseModel) obj).getId().getId() : false;
        } catch (Exception e) {
            return false;
        }
    }
}

Here's the class (Project) I want to save

@PersistenceCapable(detachable = "true", identityType = IdentityType.APPLICATION)
public class Project extends BaseModel implements BeanModelTag {

    private static final long serialVersionUID = 3318013676594981107L;

    @Persistent
    private String name;

    @Persistent
    private String description;

    @Persistent
    private Date deadline;

    @Persistent
    private Integer status;

    @Persistent
    private Key manager;

    @Persistent
    private Set<Key> team;
}

For that, I tried several things. This method below saves a NEW instance of Project with success, but when I call to for updating an already detached object, only the field deadline is updated, the other attributes aren't updated (and yet, I went in debug mode to check out if the other attributes where changed, and yes, they were, but only deadline get's saved).

public void save(BaseModel object) {
    PersistenceManager pm = PMF.getPersistenceManager();
    try {
        pm.makePersistent(object);
    } finally {
        pm.close();
    }
}

So, I tried the following code

public void update(Project object) {
    PersistenceManager pm = PMF.get().getPersistenceManager();
    try {
        pm.currentTransaction().begin();

        Project p = pm.getObjectById(Project.class, object.getId());
        p.setName(object.getName());
        p.setDeadline(object.getDeadline());
        p.setDescription(object.getDescription());
        p.setTeam(p.getTeam());
        p.setStatus(object.getStatus());

        pm.currentTransaction().commit();
    } catch (Exception e) {
        e.printStackTrace();
        pm.currentTransaction().rollback();
    } finally {
        pm.close();
    }
}

And it worked. Ok, it works in this way, but I need a generic method for all my models, so I tried this

public void update(BaseModel object) {
    PersistenceManager pm = PMF.get().getPersistenceManager();
    try {
        pm.currentTransaction().begin();

        BaseModel ob = pm.getObjectById(object.getClass(), object.getId());

        for (Field f : ob.getClass().getDeclaredFields()) {
            if (!f.toString().contains("final")) {
                f.setAccessible(true);
                for (Field g : object.getClass().getDeclaredFields()) {
                    g.setAccessible(true);
                    if (f.getName().equals(g.getName())) {
                        f.set(ob, g.get(object));
                    }
                    g.setAccessible(false);
                }
            }
            f.setAccessible(false);
        }

        pm.makePersistent(ob);
        pm.currentTransaction().commit();
    } catch (Exception e) {
        e.printStackTrace();
        pm.currentTransaction().rollback();
    } finally {
        pm.close();
    }
}

But it doesn't work at all, nothing gets saved, and yet when I System.out the attributes manually, they are changed. I tried with and without pm.makePersistent(ob); with no luck. I don't know what to do. I have 120 models in this project that inherits from BaseModel and I can't find a way to make an update that works with my model.

----------- Edit -----------

Thanks for the answer. Here's my solution for now. Of course, that printStrackTree will get out of there.

public void update(BaseModel object) {
    PersistenceManager pm = PMF.get().getPersistenceManager();
    try {
        pm.currentTransaction().begin();

        BaseModel ob = pm.getObjectById(object.getClass(), object.getId());

        for (Field f : ob.getClass().getDeclaredFields()) {
            if (!Pattern.compile("\\bfinal\\b").matcher(f.toString()).find()) {
                f.setAccessible(true);
                for (Field g : object.getClass().getDeclaredFields()) {
                    g.setAccessible(true);
                    if (f.getName().equals(g.getName())) {
                        f.set(ob, g.get(object));
                        JDOHelper.makeDirty(ob, f.getName());
                    }
                    g.setAccessible(false);
                }
                f.setAccessible(false);
            }
        }

        pm.makePersistent(object);
        pm.currentTransaction().commit();
    } catch (Exception e) {
        e.printStackTrace();
        pm.currentTransaction().rollback();
    } finally {
        pm.close();
    }
}

解决方案

Using reflection to update fields will not be detected by JDO bytecode enhanced methods. If you want to update fields direct (whether by field or by reflection) then you could call

JDOHelper.makeDirty(obj, "myFieldName");

after doing your update, and then the change will be registered by JDO and hence updated in the datastore.

这篇关于更新GAE中的对象的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆