我有一个容器对象,其中包含一组使用JDO 2.3持久保存在 Google App Engine 中的对象。我想从设置的内容中删除一个对象。使用以下测试代码,remove() 方法返回 false,但更改不会持久化,如以下代码所示。但是,集合基数减少了(这种行为让我感到惊讶)。如何更正此示例以从集合中删除指定的对象(在本例中为对象“一个”)?
我无法在 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();
}