更新GAE中的对象 [英] Updating objects in 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屋!