开发者

JDO - Updating a One-to-one child

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 co开发者_开发问答ntent 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>


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.


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


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


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.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜