簡體   English   中英

GAE數據存儲區不會在嵌入式JDO類中持久保留擁有的1:1關系

[英]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.autoCreateDatastoreTxnstrue在你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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM