JDO-обновление одного ребенка к одному
У меня есть рецепт. Каждый рецепт имеет свое изображение. Таким образом, моя сущность выглядит примерно так:
@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 ответа:
Я думаю, что реализация AppEngine JDO хранит собственные отношения в виде родительских ключей. Когда вы делаете myImageA дочерним объектом recipe1, appengine устанавливает родительский объект MyImage в recipe1.
Я не эксперт в этом, но я предполагаю, что когда вы делаете myImageB дочерним элементом recipe1, appengine просто устанавливает родительский элемент другого объекта MyImage в recipe1. Когда он идет для получения
myImage
, он ищет изображение с родителемrecipe1
, и все еще находитmyImageA
, даже хотяmyImageB
все еще сидит там.Опять же, я предполагаю. Я бы хотел, чтобы был вариант "отправить догадку".
TL; DR : я бы попробовал удалить
myImageA
явно перед установкойmyImageB
. Это нарушило бы любую другую ссылку наmyImageA
, но если вы надеетесь использовать ее из других контекстов, то отношения собственности в любом случае неуместны.Такого рода запутанная путаница-вот почему я бросил отношения JDO & owned и научился любить объективировать. Они также ограничьте свои возможности для групп сущностей, что добавляет еще одно измерение тумана.
Я думаю, что вы должны вызвать
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(); }
То, что работало для меня, было получение старого объекта, который нужно было обновить, затем изменение объекта, а затем его хранение. Корректировка вашего кода дает нам:
Это в основном то, что я сделал, и это, кажется, работает.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(); }