I have three @PC classes:
@PersistenceCapable
class A {
@PrimaryKey @Persistent(valueStrategy = IdGeneratorStrategy.IDENTITY)
@Extension(vendorName = "datanucleus", key = "gae.encoded-pk", value = "true")
private String id;
@Persistent @Embedded
private B b;
public void setB(B b){
this.b=b;
}
}
@PersistenceCapable @EmbeddedOnly
class B {
@Persistent
private String someInfo;
@Persistent
private C c;
public void setC(C c){
this.c=c;
}
}
@PersistenceCapable
class C {
@PrimaryKey @Persistent(valueStrategy = IdGeneratorStrategy.IDENTITY)
@Extension(vendorName = "datanucleus", key = "gae.encoded-pk", value = "true")
private String id;
@Persistent
private String value;
public void setValue(String value){
this.value=value;
}
}
I want to achieve that B is persisted to same entity as A while holding a reference to C but GAE does not let me, I get a following exception on commit:
Detected attempt to establish A(1) as the parent of C(2) but the entity identified by C(2) has already been persisted without a parent. A parent cannot be established or changed once an object has been persisted.
in this code:
A a = new A();
B b = new B();
C c = new C();
c.setValue("foo");
b.setC(c);
a.setB(b);
m.makePersistent(a);
additionally: a look into DatastoreViewer shows me that C has been persisted! But A is missing. This might happen because I do not explicitelly rollback the transaction on exception which is not relevant in this case, but reveals that C is written before its parent A.
what am I missing? Tx
Update 2:
as suggested I have enabled transaction explicitely:
Transaction tx = pm.currentTransaction();
try {
tx.begin();
pm.makePersistent(a);
tx.commit();
} finally {
if (tx.isActive()) {
tx.rollback();
}
pm.close();
}
same exception was thrown as when doing .makePersistent() w/o explicit transaction. Then I set disabled the global cross tx option in JDO config:
<property name="datanucleus.appengine.datastoreEnableXGTransactions" value="false"/>
and now get a different exception with a possible hint:
cross-group transaction need to be explicitly specified, see
TransactionOptions.Builder.withXGfound both Element {
type: "A"
id: 1
}
and Element {
type: "C"
id: 2
}