2

Google App Engine と JDO を使用して「ネストされた」データを更新する適切な方法がわかりません。RecipeJDOIngredientJDOがあります。

特定のレシピ インスタンスの材料を新しい材料リストに完全に置き換えたいと考えています。次に、そのレシピが (再) 永続化されると、以前に添付された材料はデータストアから完全に削除され、新しいものは永続化され、レシピに関連付けられます。

何かのようなもの:

  // retrieve from GAE datastore
  RecipeJDO recipe = getRecipeById();    

  // fetch new ingredients from the user
  List<IngredientJDO> newIngredients = getNewIngredients();
  recipe.setIngredients(newIngredients);

  // update the recipe w/ new ingredients
  saveUpdatedRecipe(recipe);

これは、データストアから返された (デタッチされた) レシピ オブジェクトを直接更新すると正常に機能します。ただし、RecipeJDOをコピーして前述の更新を行うと、最終的に新しい材料が追加され、レシピがデータストアから再取得されるときに古い材料と一緒に返されます。(なぜわざわざコピーする必要があるのでしょうか? 私はフロント エンドで GWT を使用しているので、JDO オブジェクトを DTO にコピーしています。ユーザーはそれらをフロント エンドで編集し、それらをバックエンドに送信して更新します。データストア。)

手動で作成したオブジェクト (id を含むすべてのフィールドを設定) と、PersistenceManager によって返されたインスタンスでの操作で異なる結果が得られるのはなぜですか? 明らかに、JDO のバイトコード拡張が何らかの形で関与しています。

更新されたレシピを永続化する前に、古い材料を明示的に削除した方がよいでしょうか?

(余談ですが、ORM に不満を感じていて、単純な古い RDBMS に戻りたいと思っている人はいますか? :-)

4

3 に答える 3

4

簡潔な答え。これに変更RecipeJDO.setIngredients()します。

public void setIngredients(List<IngredientJDO> ingredients) {
  this.ingredients.clear();
  this.ingredients.addAll(ingredients);
}

RecipeJDO をフェッチすると、ingredientsリストは実際の ではなくArrayList、含まれている要素の永続性を処理する動的プロキシです。交換してはいけません。

持続性マネージャーが開いている間、リストを反復処理しingredientsたり、アイテムを追加したり、アイテムを削除したりできます。持続性マネージャーが閉じられたとき (または、トランザクション中の場合はトランザクションがコミットされたとき) に変更が持続されます。トランザクションなしで更新を行う方法は次のとおりです。

public void updateRecipe(String id, List<IngredientDTO> newIngredients) {
  List<IngredientJDO> ingredients = convertIngredientDtosToJdos(newIngredients);
  PersistenceManager pm = PMF.get().getPersistenceManager();
  try {
    RecipeJDO recipe = pm.getObjectById(RecipeJDO.class, id);
    recipe.setIngredients(ingredients);
  } finally {
    pm.close();
  }
}

オブジェクトをまったく変更しないIngredientJDO(置き換えて読み取るだけ) 場合はSerializable、JDO オブジェクトではなくオブジェクトにすることをお勧めします。Ingredientこれを行うと、 GWT RPC コードでクラスを再利用できる場合があります。

ちなみに、RecipeJDO オブジェクトではない場合でも、setIngredients()メソッドでコピーを作成する必要があります。そうしないと、誰かがこれを行うことができます。

List<IngredientJDO> ingredients = new ArrayList<IngredientJDO>;
// add items to ingredients
recipe.setIngredients(ingredients);
ingredients.clear(); // Woops! Modifies Recipe!
于 2009-09-27T02:57:24.270 に答える
0

私は同じ問題に直面しています!makePersistent() を呼び出して既存の ID/キーを割り当てて、既存のエンティティを更新したいと思います! ネストされたオブジェクトを除いて、更新は正常に機能します! ネストされたオブジェクトは、置き換えられるのではなく、古いオブジェクトに追加されますか? これが意図した動作なのか、それともバグなのかわかりません。上書きは、新しいエンティティを挿入するのと同じ効果があると期待しています!

最初に古いエンティティを削除し、同じトランザクションで新しいエンティティを永続化するのはどうですか? これは機能しますか?これを試してみましたが、エンティティが完全に削除されましたか?! 理由はわかりません(削除した直後にフラッシュを試みましたが)!

于 2010-03-08T10:36:40.477 に答える
0

@NamshubWriter、この投稿をキャッチできるかどうかわかりません...コメントに関して、

(Stripes と JSP を使用した場合、レシピと材料の GWT RPC および GWT モデル表現を回避できます)

Stripes と JSP を使用していますが、同じ問題に直面していますユーザーがフォームを送信すると、Stripes はエンティティ オブジェクトを最初からインスタンス化するため、JDO はエンティティ オブジェクトを完全に認識しません。ルート オブジェクトで PersistenceManager.makePersistent を呼び出すと、以前のバージョンが正しく上書きされます。1 つの例外を除いて、そのオブジェクトは以前のバージョンのList<child>に追加されます。

(オブジェクト フィールドを手動でコピーするよりも良い) 解決策を提案できれば幸いです。

(Stripes は非常にプラグ可能であるため、エンティティ オブジェクトのインスタンス化方法をオーバーライドできるのではないかと考えています...)

于 2010-08-15T18:21:49.800 に答える