JDO - 更新一对一子项

发布于 2024-10-31 03:58:44 字数 1591 浏览 0 评论 0原文

我有一个食谱。每个食谱都有一个图像。所以我的实体看起来像

@PersistenceCapable
public class Recipe {
   @PrimaryKey
   @Persistent(valueStrategy = IdGeneratorStrategy.IDENTITY)
   private Key key;
   @Persistent
   private MyImage myImage;

当我第一次创建食谱时,效果很好,图像是 也添加了,我可以查看它。但是当我去更新它时 当

   PersistenceManager pm = PMF.get().getPersistenceManager();
   Recipe r = pm.getObjectById(Recipe.class, recKey);
   try {
       r.setImage(newImage);
   } finally {
       pm.close();
   }

新图像添加到数据存储中时,但是当我尝试获取它时 从菜谱中,菜谱仍然指向我的旧图像 数据存储。这是正常的吗?我该如何解决这个问题?

这是我的 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>

I have a Recipe. Each Recipe has an image. So my entity looks something like

@PersistenceCapable
public class Recipe {
   @PrimaryKey
   @Persistent(valueStrategy = IdGeneratorStrategy.IDENTITY)
   private Key key;
   @Persistent
   private MyImage myImage;

When I create the Recipe the first time, it works great, the image is
added as well and I can view it. However when I go and update it such
as

   PersistenceManager pm = PMF.get().getPersistenceManager();
   Recipe r = pm.getObjectById(Recipe.class, recKey);
   try {
       r.setImage(newImage);
   } finally {
       pm.close();
   }

the new image is added to the data-store, but when I try and fetch it
from within the recipe, the recipe still points to the old image in my
data-store. Is this normal? How can I fix this?

Here is the content of my jdoconfig.xml file

<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>

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

倾其所爱 2024-11-07 03:58:44

我认为 JDO 的 AppEngine 实现以父键的形式存储拥有的关系。当您将 myImageA 设置为recipe1 的子级时,appengine 将 MyImage 实体的父级设置为recipe1。

我不是这方面的专家,但我猜测当您将 myImageB 作为recipe1 的子级时,appengine 只是将另一个 MyImage 实体的父级设置为recipe1。当它去检索 myImage 时,它会查找父级为 recipe1 的图像,并且仍然找到 myImageA,即使 myImageB 仍然坐在那里。

我再次猜测。我希望有一个“提交猜测”选项。

TL;DR:我会在设置 myImageB 之前尝试显式删除 myImageA。这会破坏对 myImageA 的所有其他引用,但如果您希望从其他上下文中使用它,那么拥有的关系无论如何都是不合适的。

这种令人困惑的混淆就是我放弃 JDO 和 JDO 的原因。完全拥有关系并学会了热爱 Objectify。它们还限制了您对实体组的选择,这增加了雾的另一个维度。

I think the AppEngine implementation of JDO stores owned relationships in the form of parent keys. When you make myImageA a child of recipe1, appengine sets the parent of a MyImage entity to recipe1.

I'm not an expert on this, but I'm guessing that when you make myImageB a child of recipe1, appengine just sets the parent of another MyImage entity to recipe1. When it goes to retrieve myImage, it looks for an image with a parent of recipe1, and still finds myImageA, even though myImageB is still sitting there.

Again, I'm guessing. I wish there was a "Submit Guess" option.

TL;DR: I'd try deleting myImageA explicitly before setting myImageB. That would break every other reference to myImageA, but if you're hoping to use it from other contexts an owned relationship is inappropriate anyway.

This kind of confusing mixup is why I dropped JDO & owned relationships altogether and learned to love Objectify. They also constrain your options for entity groups, which adds another dimension of fog.

歌入人心 2024-11-07 03:58:44

我认为您必须在设置新图像对象后调用 pm.makePercient(r); 才能实际保留您的更改。

I think you got to call pm.makePersistent(r); after setting the new image object to actually persist your change.

无言温柔 2024-11-07 03:58:44

不需要执行 pm.makePercient(r); 因为 Recipe 已经是持久的。
但在您的代码示例中,您使用非事务性读取,这意味着您可以在没有事务的情况下从数据存储区读取实例。
但如果你想进行持久修改,你需要使用事务。

   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();
   }

It is not required to do pm.makePersistent(r); because the Recipe is already persistent.
But in your code example you use non transactional read which means you can read instances from the datastore without a Transaction.
But if you want to do persistent modifications you need to use a Transaction.

   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();
   }
小清晰的声音 2024-11-07 03:58:44

对我有用的是获取需要更新的旧对象,然后更改该对象,然后存储它。调整你的代码给了我们:

   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();
   }

这基本上就是我所做的,而且似乎有效。

What worked for me was getting the old object that needed to be updated then changing the object then storing it. Adjusting your code gives us:

   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();
   }

This is basically what I did and it seems to work.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文