2

私は GAE 1.7.0 w/ JDO(DataNucleus) を使用しています。コレクション属性を持つクラスを永続化すると、削除されたコレクション メンバーがデータストアから削除されません。切り離されたコピーからコレクション メンバーを削除します。新しいメンバーが正しく追加され、既存のメンバーが削除されないため、コレクションが増えるだけです。

@PersistenceCapable(identityType = IdentityType.APPLICATION, detachable="true")
public class Parent{
    @PrimaryKey
    @Persistent(valueStrategy = IdGeneratorStrategy.IDENTITY)
    private Long id;

    @Persistent(defaultFetchGroup="true", dependentElement="true")
    private List<Child> children = new ArrayList<Child>(0);

}

@PersistenceCapable(identityType = IdentityType.APPLICATION, detachable="true")
public class Child implements Serializable {

    @PrimaryKey
    @Persistent(valueStrategy = IdGeneratorStrategy.IDENTITY)
    @Extension(vendorName="datanucleus", key="gae.encoded-pk", value="true")
    private String id;

    @Persistent
    @Extension(vendorName="datanucleus", key="gae.parent-pk", value="true")
    private String parentId;
    ....
}

...
parent = pm.detachCopy(resultFromQuery);
// parent looks correct in dubugger: all children are fetched (and detached)
....
parent.getChildren().clear();
parent.getChildren().addAll(newChildren);
for (Child child: parent.getChildren())
    child.setParentId(KeyFactory.createKeyString("Parent", parent.getId()));
// parent looks good in the debugger: old children were removed and new ones added
...
PersistenceManager pm = PMF.get().getPersistenceManager();
try {
    pm.currentTransaction().begin();
    pm.makePersistent(parent);
    pm.currentTransaction().commit();
} catch (Exception e) {
} finally {
    if (pm.currentTransaction().isActive())
        pm.currentTransaction().rollback();
    if (!pm.isClosed())
        pm.close();
}
// problem in datastore: new children were created, old ones not removed

トランザクションで (オブジェクトをデタッチせずに) query-remove-persist を実行すると、問題が解決することに気付きました。これは一時的な回避策ですが、デタッチされたオブジェクトを更新したいと思います。

4

1 に答える 1

1

私はJDOの専門家ではありませんが、ここに行きます....

各エンティティParentとそれに関連するChildエンティティは、同じエンティティ グループに属します。したがって、トランザクション内でデータストアの更新を行う必要があります。これは、特定のエンティティ グループが 1 秒あたり約 1 回以上の頻度で更新されない可能性があるためです。また、トランザクション内では拡張マジックが機能します。子の追加と削除、フィールド値の設定などを処理する隠し追加 Java バイトコードです。

これを行いたくない場合、1 つの方法は、Childエンティティのリストを に格納しないことParentです。Child代わりに ID や主キーのリストを保存します。これにより、それぞれChildが独自のエンティティ グループになります。Parentただし、その場合でも、各(リスト)を更新できるのは 1 秒に 1 回だけです。

于 2012-09-17T13:08:03.310 に答える