JDO 2.3を使用して Google App Engine に永続化される一連のオブジェクトを含むコンテナ オブジェクトがあります。セット内容からオブジェクトを削除したい。次のテスト コードでは、remove() メソッドは false を返しますが、次のコードが示すように、変更は保持されません。ただし、セットのカーディナリティは減少します (この動作には驚かされます)。このサンプルを修正して、指定されたオブジェクト (この場合はオブジェクト「1」) をセットから削除するにはどうすればよいですか?
JDO ドキュメントで関連するものを見つけることができませんでした。等値チェックとハッシュは、この記事に基づいています。
ログ レベルを上げたコンソール ログのダンプはこちら(更新: これはトランザクションのないバージョンです)。
トランザクションを含むコンソール ログのダンプはこちらにあります。
コンテナ.java
import java.util.HashSet;
import java.util.Set;
import javax.jdo.annotations.FetchGroup;
import javax.jdo.annotations.PersistenceCapable;
import javax.jdo.annotations.Persistent;
import javax.jdo.annotations.PrimaryKey;
@PersistenceCapable(detachable = "true")
@FetchGroup(name = "withContents", members = { @Persistent(name = "contents") })
public class Container
{
@PrimaryKey
private String id;
@Persistent(dependentElement = "true")
private Set<Containee> contents;
public Set<Containee> getContents()
{
return contents;
}
public Container(String id)
{
super();
this.id = id;
contents = new HashSet<Containee>();
}
}
コンテナ.java
import javax.jdo.annotations.Extension;
import javax.jdo.annotations.IdGeneratorStrategy;
import javax.jdo.annotations.PersistenceCapable;
import javax.jdo.annotations.Persistent;
import javax.jdo.annotations.PrimaryKey;
@PersistenceCapable(detachable = "true")
public class Containee
{
@SuppressWarnings("unused")
@PrimaryKey
@Persistent(valueStrategy = IdGeneratorStrategy.IDENTITY)
@Extension(vendorName = "datanucleus",
key = "gae.encoded-pk", value = "true")
private String id;
@Persistent
private String friendlyName;
public String getFriendlyName()
{
return friendlyName;
}
public Containee(String friendlyName)
{
this.friendlyName = friendlyName;
}
@Override
public boolean equals(Object other)
{
if (other instanceof Containee)
{
Containee that = (Containee) other;
return this.getFriendlyName().equals(that.getFriendlyName());
}
return false;
}
@Override
public int hashCode()
{
return friendlyName.hashCode();
}
}
テスト スニペット(RemoteService の一部としてサーバー側で実行)
...
System.out.println("Fetching...");
Container after = pm.getObjectById(Container.class, "test");
// prints 2
System.out.println("Pre-remove set cardinality "
+ after.getContents().size());
// prints "true"
System.out.println("Post-store containment: "
+ after.getContents().contains(one));
for (Containee e : after.getContents())
{
System.out.println(e.getFriendlyName());
}
System.out.println("Mark");
boolean result = after.getContents().remove(one);
System.out.println("End Mark");
System.out
.println("'after' object class: " + after.getContents().getClass());
// prints "false" (!?!?)
System.out.println("Post-store removal: " + result);
// prints 1 (...?)
System.out.println("Post-remove set cardinality: "
+ after.getContents().size());
...
編集:
トランザクションでスニペットをテストする
Container before = new Container("test");
Containee one = new Containee("one");
Containee two = new Containee("two");
Containee three = new Containee("three");
before.getContents().add(one);
before.getContents().add(two);
before.getContents().add(three);
// prints "true"
System.out.println("Pre-store containment: "
+ before.getContents().contains(two));
// prints "true"
System.out.println("Pre-store removal: "
+ before.getContents().remove(two));
PersistenceManager pm = pmf.getPersistenceManager();
try
{
pm.makePersistent(before);
}
finally
{
pm.close();
}
pm = pmf.getPersistenceManager();
pm.getFetchPlan().addGroup("withContents");
Transaction tx = pm.currentTransaction();
try
{
System.out.println("Fetching...");
Container after = pm.getObjectById(Container.class, "test");
// prints 2
System.out.println("Pre-remove set cardinality "
+ after.getContents().size());
// prints "true"
System.out.println("Post-store containment: "
+ after.getContents().contains(one));
for (Containee e : after.getContents())
{
System.out.println(e.getFriendlyName());
}
tx.begin();
System.out.println("Mark");
boolean hrm = after.getContents().remove(one);
System.out.println("End Mark");
tx.commit();
System.out
.println("'after' object class: " + after.getContents().getClass());
// prints "false" (!?!?)
System.out.println("Post-store removal: " + hrm);
// prints 1 (...?)
System.out.println("Post-remove set cardinality: "
+ after.getContents().size());
}
finally
{
System.out.println("Finalizing transaction...");
if (tx.isActive())
{
System.out.println("Rolling back...");
tx.rollback();
}
}
pm.close();
pm = pmf.getPersistenceManager();
pm.getFetchPlan().addGroup("withContents");
try
{
System.out.println("Fetching again...");
Container after = pm.getObjectById(Container.class, "test");
// prints 2
System.out.println("Final set cardinality "
+ after.getContents().size());
}
finally
{
pm.close();
}