Java JDO-更新一对一子级
我有一个食谱。每个食谱都有一个图像。所以我的实体看起来像Java JDO-更新一对一子级,java,google-app-engine,jdo,Java,Google App Engine,Jdo,我有一个食谱。每个食谱都有一个图像。所以我的实体看起来像 @PersistenceCapable public class Recipe { @PrimaryKey @Persistent(valueStrategy = IdGeneratorStrategy.IDENTITY) private Key key; @Persistent private MyImage myImage; 当我第一次创建菜谱时,效果非常好,图像非常清晰 也添加了,我可以查看它。但是当
@PersistenceCapable
public class Recipe {
@PrimaryKey
@Persistent(valueStrategy = IdGeneratorStrategy.IDENTITY)
private Key key;
@Persistent
private MyImage myImage;
当我第一次创建菜谱时,效果非常好,图像非常清晰
也添加了,我可以查看它。但是当我去更新它的时候
作为
新图像被添加到数据存储中,但是当我尝试获取它时
在配方中,配方仍然指向我的
数据存储。这正常吗?我怎样才能解决这个问题
这是我的jdoconfig.xml文件的内容
<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>
我想你应该打电话给pm.makePersistent(r)将新图像对象设置为实际保留更改后的代码>。无需执行pm.makePersistent(r)代码>因为配方已经是持久的。
但在代码示例中,您使用非事务性读取,这意味着您可以从数据存储中读取实例,而无需事务。
但是,如果要进行持久性修改,则需要使用事务
PersistenceManager pm = PMF.get().getPersistenceManager();
Transaction txn = pm.currentTransaction();
txn.begin();
Recipe r = pm.getObjectById(Recipe.class, recKey);
try {
r.setImage(newImage);
txn.commit();
} finally {
pm.close();
}
我认为JDO的AppEngine实现以父键的形式存储所拥有的关系。当您将myImageA设置为recipe1的子级时,appengine会将MyImage实体的父级设置为recipe1
我不是这方面的专家,但我猜当您将myImageB设置为recipe1的子对象时,appengine只是将另一个MyImage实体的父对象设置为recipe1。当它去检索myImage
时,它会查找父级为recipe1
的图像,并且仍然会找到myImageA
,即使myImageB
仍在那里
再说一遍,我猜。我希望有一个“提交猜测”选项
TL;DR:在设置myImageB
之前,我会尝试显式删除myImageA
。这将打破对myImageA的所有其他引用,但如果您希望从其他上下文中使用它,那么拥有的关系无论如何都是不合适的
这种令人困惑的混乱正是我放弃JDO&完全拥有关系并学会爱客观化的原因。它们还限制了实体组的选项,这增加了雾的另一个维度。对我来说,有效的方法是获取需要更新的旧对象,然后更改对象,然后存储它。调整您的代码将为我们提供:
PersistenceManager pm = PMF.get().getPersistenceManager();
Recipe r = pm.getObjectById(Recipe.class, recKey);
MyImage newImage = r.getMyImage();
newImage.setImage(newImageFile);
try {
r.setImage(newImage);
pm.makePersistent(r);
} finally {
pm.close();
}
这基本上就是我所做的,而且似乎有效 你能发布你的jdoconfig.xml
的内容吗。您是否更改了该文件中的任何内容,特别是datanucleus.appengine.autoCreateDatastoreTxns
?我还尝试了事务。同样的结果。图像添加到数据存储中,但配方对象仍然指向第一个图像。如果执行pm.refresh(r),会发生什么情况?在tx.commit()之前添加该图像代码>。同样的结果:(我认为您不必使用事务来持久化对对象的更改。猜测:AppEngine只需在关闭pm时对您更改的对象调用put
。您是否发现了这一点?我也遇到了同样的问题。希望赏金会有所帮助。@Lumpy,不幸的是,我完全放弃了所有关系,以支持of无主关系。我在网上找不到任何帮助,这里的声誉也帮不上忙。是的,不幸的是,我还放弃了app engine的JDO。这是一个标准层,使我的app engine应用程序在google世界之外工作。objectify在google Store之外工作吗?不,objectify是100%特定于app engine的:(这正是我最终所走的道路。如果您没有创建新对象,而是获取该对象,更新它,然后存储它,这似乎是可行的。在已经持久化的对象上调用makePersistent应该是不必要的;关闭PersistenceManager应该可以保存更改。
PersistenceManager pm = PMF.get().getPersistenceManager();
Recipe r = pm.getObjectById(Recipe.class, recKey);
MyImage newImage = r.getMyImage();
newImage.setImage(newImageFile);
try {
r.setImage(newImage);
pm.makePersistent(r);
} finally {
pm.close();
}