JDO - Обновление ребенка один на один - PullRequest
3 голосов
/ 07 апреля 2011

У меня есть рецепт.Каждый рецепт имеет изображение.Так что моя сущность выглядит примерно так:

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

Ответы [ 4 ]

2 голосов
/ 07 июня 2011

Я думаю, что реализация JDO в AppEngine хранит собственные отношения в форме родительских ключей.Когда вы делаете myImageA дочерним по отношению к recipe1, appengine устанавливает для родительского объекта сущности MyImage recipe1.

Я не эксперт в этом, но я предполагаю, что когда вы делаете myImageB дочерним по отношению к recipe1,appengine просто устанавливает родителя другого объекта MyImage в recipe1.Когда он пытается получить myImage, он ищет изображение с родителем recipe1 и все еще находит myImageA, хотя myImageB все еще сидит там.

Опять яугадывание.Хотелось бы, чтобы была опция «Угадай».

TL; DR : Я бы попытался удалить myImageA явно перед установкой myImageB.Это нарушило бы все остальные ссылки на myImageA, но если вы надеетесь использовать его в других контекстах, отношения с собственником в любом случае неуместны.

Этот путаница такого рода является причиной того, что я вообще отбросил отношения JDO и отношения с владельцеми научился любить объективировать.Они также ограничивают ваши параметры для групп объектов, что добавляет еще одно измерение тумана.

0 голосов
/ 10 июня 2011

Для меня работало получение старого объекта, который нужно было обновить, затем изменение объекта и его сохранение. Корректировка вашего кода дает нам:

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

Это в основном то, что я сделал, и, кажется, работает.

0 голосов
/ 08 апреля 2011

Не обязательно делать 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();
   }
0 голосов
/ 08 апреля 2011

Я думаю, вам нужно позвонить pm.makePersistent(r); после установки нового объекта изображения, чтобы фактически сохранить ваши изменения.

...