1

내의 1 개 관계 I 세 @PC 클래스가있다 : C 참조 채GAE 데이터 저장소가 소유 지속되지 않습니다 1 : 매립 JDO 클래스

@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가 B를 달성하고자하는이 같은 동일 엔티티에 유지된다 하지만 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 앞에 쓰여 있음을 나타냅니다.

무엇이 누락 되었습니까? 텍사스

업데이트 2 :

내가 명시 적으로 트랜잭션을 사용하도록 설정 한 제안 :

Transaction tx = pm.currentTransaction(); 
try { 
    tx.begin(); 
    pm.makePersistent(a); 
    tx.commit(); 
} finally { 
    if (tx.isActive()) { 
    tx.rollback(); 
    } 
    pm.close(); 
} 

같은 예외가 명시 적 트랜잭션 오 승/.makePersistent()를 수행 할 때로 던져졌다.

<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 
} 
+1

데이터를 지속하려는 코드를 표시 하시겠습니까? – skirsch

+0

질문을 업데이트했습니다. 나는 노골적으로 트랜잭션을 사용하지 않는다는 것을 안다. – comeGetSome

+0

게시물에 'makePersistent'를 추가했는데 어떤 오브젝트가 *? 당신이 전화를 걸 때 C의 라이프 사이클 상태는 무엇입니까? 로그는 그 모든 것을 알려줍니다. – DataNucleus

답변

0

확인 마침내 나는 지점을 가지고,

아직 나는 거기에 뭔가를 그리워 데이터 저장소의 JDO 구현 (그 DataNucleus 작업이 경우 나도 몰라)라고 생각합니다. transactions on DataStore에 따르면 일반적으로 조상을 따르는 엔티티 만 한 번에 지속될 수 있습니다. 예외적으로 GAE 클레임은 번호에 의해 제한되지만 관련이없는 엔티티 경로는 유지할 수있는 교차 그룹 트랜잭션을 지원합니다. 둘 다 내 경우에는 적용되지 않았다.

가난한 솔루션은 데이터 저장소 내 POJO를에 확장 따르는 권리를 얻을 수 있도록 상위 경로를 설명하는 유일한 가능한 kandidate있는 키 (GAE 독점)를 통해 소유되지 않은 관계, 시행하는 지금 :

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. 

하나의 문제는 내가 여기에 대리 키를 사용할 수 없다는 것입니다, 다른 것은 내가 그렇게 비 JDO 및 비 BO 코드 내 POJO를에있을 싶지 않는 것입니다 부모 - 자식 관계는 JDO-DAO 구현에서 어딘가에 확립되어야합니다. 퍼시스턴스 그래프가 역전되어 보이는 것처럼 DataNucleus GAE 포트가 다소 부정확하다고 생각합니다.

0

난 당신이 최대로 설정하면이 문제가 사라있어 가정 그럼 난 글로벌 크로스 JDO의 설정에서 텍사스 옵션을 비활성화 세트 트랜잭션 경계. documentation은 내가하는 일이 가능해야한다고 주장하지만 jdoconfig.xmldatanucleus.appengine.autoCreateDatastoreTxnstrue으로 설정했다고 가정합니다.
따라서 C은 자신의 엔티티 그룹과 자체 트랜잭션으로 저장됩니다. 두 번째 거래에서는 A를 저장하고, 따라서 금지되어 A의 엔티티 groupy에 C를 재 할당하려고 :

엔티티가

을 이렇게 만들 때 개체 그룹에만 할당 할 수 있기 때문에 : 거래를 설정하십시오 (권장 사항대로).

+0

감사합니다,하지만 그것을 확인했지만 아직 성공 (내 질문 업데이트) – comeGetSome

+0

그것은 트랜잭션이 설립 된 후 개체를 만드는 데 도움이 될 수 있습니다. GAE/JDO 조합은 때로는 재미있는 뉘앙스를 필요로합니다 ... – skirsch

관련 문제