[英]difference of owned one-to-many relationship between GAE/J low level datastore API and DataNucleus JDO
[英]GAE datastore will not persist owned 1:1 relationship within embedded JDO class
我有三個@PC類:
@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;
}
}
我想實現B在持有對C的引用的同時與A保持相同的實體,但是GAE不允許我這樣做,提交時出現以下異常:
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.
在此代碼中:
A a = new A();
B b = new B();
C c = new C();
c.setValue("foo");
b.setC(c);
a.setB(b);
m.makePersistent(a);
另外:對DatastoreViewer的查看向我展示了C已被保留! 但是A不見了。 之所以會發生這種情況,是因為我沒有明確地在異常情況下不回滾該事務(在這種情況下不相關),但是顯示C是在其父A之前寫入的。
我想念什么? Tx
更新2:
如建議的那樣,我明確地啟用了事務:
Transaction tx = pm.currentTransaction();
try {
tx.begin();
pm.makePersistent(a);
tx.commit();
} finally {
if (tx.isActive()) {
tx.rollback();
}
pm.close();
}
與執行.makePersistent()而沒有顯式事務時,拋出相同的異常。 然后我在JDO config中設置了禁用global cross tx選項:
<property name="datanucleus.appengine.datastoreEnableXGTransactions" value="false"/>
現在得到一個帶有可能提示的不同異常:
cross-group transaction need to be explicitly specified, see
TransactionOptions.Builder.withXGfound both Element {
type: "A"
id: 1
}
and Element {
type: "C"
id: 2
}
我想如果您設置一個事務邊界來解決這個問題,那么您的問題就消失了。 盡管文件稱,你做什么,應該是可能的,我假設你已經設置datanucleus.appengine.autoCreateDatastoreTxns
到true
在你jdoconfig.xml
。
因此, C
與自己的實體組一起存儲在自己的事務中。 在第二筆交易中,您存儲A
,然后嘗試將C
重新分配給A
的實體組,這是被禁止的:
因為只能在創建實體時分配實體組
因此:建立交易(建議)。
好的,最后我明白了,
但是我認為DataStore的JDO實現(我不知道它的DataNucleus工作是否)會錯過一些東西。 根據DataStore上的交易,通常只能一次性保留沿祖先的實體,特別是GAE 聲稱支持跨組交易,該交易受數量限制,但可以保留不相關的實體路徑。 兩者均不適用於我的情況。
現在, 較差的解決方案是通過密鑰(GAE專有)強制執行無主關系,這是描述祖先路徑的唯一可能的候選對象,以便DataStore正確地執行我的POJO擴展:
class A {
...
private String naturalPK;
public String getNaturalPK(){
return naturalPK;
}
...
}
class C {
...
public void setId(String id){
this.id=id;
}
...
}
和持久性代碼:
tx.begin();
// we have to assign parent/child keys to enforce ancestor path
Key parentKey = KeyFactory.createKey("A", A.getNaturalPK());
a.setId(KeyFactory.keyToString(parentKey));
// now build child key
a.getB().getC().setId(KeyFactory.createKeyString(parentKey, "C", A.getNaturalPK()));
pm.makePersistent(offerer);
tx.commit(); // works.
一個問題是我不能在這里使用代理鍵,另一件事是我不想在我的POJO中使用非JDO和非BO代碼,因此必須在JDO-DAO實現中的某個地方建立父子關系。 。 我猜想DataNucleus GAE端口在這里做得有些不准確,因為持久性圖似乎要逆轉:)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.