2009-07-21 4 views
2

J'utilise Google App Engine en combinaison avec Google Web Toolkit pour écrire un outil de suivi des bogues (pour voir de quoi les technologies sont capables). Modelé d'après le traqueur de problème de Google Code, j'ai décidé qu'un problème peut avoir 0 ou plusieurs étiquettes, qui peuvent être définies au préalable (disons dans les paramètres).L'enfant un-à-plusieurs a déjà été conservé sans parent

La classe d'étiquettes (CustomLabel):

@PersistenceCapable(identityType = IdentityType.APPLICATION) 
public class CustomLabel implements Serializable { 
    @PrimaryKey 
    @Persistent(valueStrategy = IdGeneratorStrategy.IDENTITY) 
    @Extension(vendorName="datanucleus", key="gae.encoded-pk", value="true") 
    private String encodedKey; 

    @Persistent 
    @Extension(vendorName="datanucleus", key="gae.pk-id", value="true") 
    private Long keyId; 

    /** 
    * label caption. 
    */ 
    @Persistent 
    private String caption; 

    // Unimportant getters/setters 
} 

Maintenant la classe parente (numéro):

@PersistenceCapable(identityType = IdentityType.APPLICATION) 
public class Issue implements Serializable { 
    private static final long serialVersionUID = 1L; 

    @PrimaryKey 
    @Persistent(valueStrategy = IdGeneratorStrategy.IDENTITY) 
    private Long id; 

    // Replacing the Long key by this key doesn't make a difference 
    // @PrimaryKey 
    // @Persistent(valueStrategy = IdGeneratorStrategy.IDENTITY) 
    // @Extension(vendorName="datanucleus", key="gae.encoded-pk", value="true") 
    // private String encodedKey; 

    @Persistent 
    private String summary; 

    @Persistent 
    private String description; 

    @Persistent 
    private ArrayList<CustomLabel> labels; 

    // Other details 
} 

Quand je suis en train de persister un nouveau problème avec CustomLabels existants que je reçois ce qui suit exception:

org.datanucleus.exceptions.NucleusUserException: Detected attempt to establish Issue(11) as the parent of CustomLabel(1) but the entity identified by CustomLabel(1) has already been persisted without a parent. A parent cannot be established or changed once an object has been persisted. 

Comment cela peut-il être résolu? Je ne peux pas utiliser Key et créer une relation sans propriétaire, puisque j'envoie les objets à l'interface GWT (qui est compilé en Javascript et com.google.appengine.api.datastore.Key n'est pas supporté). En outre, cela briserait l'intégrité référentielle, ce qui n'est pas souhaitable.

Répondre

7

Vous ne pouvez pas affecter un élément CustomLabel existant en tant qu'élément enfant à un nouveau problème. Chaque entité CustomLabel ne peut appartenir qu'à un objet Issue, en raison de la manière dont datanucleus gère les relations. Il place à la fois l'objet parent et l'objet enfant dans le même groupe d'entités. Une entité ne peut appartenir qu'à un groupe d'entités. Donc, disons que vous créez une étiquette personnalisée appelée "nastybug" et que vous la persistez. Il appartient maintenant à un groupe d'entités X. Lorsque vous créez un nouveau problème, et que vous persistez à le faire, il appartiendra à un groupe d'entités Y. Datanucleus (et le magasin de données google) ne vous permettra pas de stocker une entité du groupe X dans le groupe Y.

Si vous voulez que les étiquettes soient partagées entre les problèmes, vous devrez utiliser une relation sans propriétaire. Vous avez raison de dire que vous ne pouvez pas passer une clé à travers le mécanisme RPC de GWT, donc vous devrez peut-être traduire vos objets JDO sous une autre forme avant de les envoyer.

Vous pouvez lire sur les groupes d'entités here

+0

Merci, qui explique beaucoup , même si c'est un peu bizarre, ayant un arrière-plan db relationnel :) – Mythica

4

Utilisez @Unowned pour votre liste:

import com.google.appengine.datanucleus.annotations.Unowned; 
... 
@Persistent 
@Unowned 
private List<Category> categories; 

Et PrimaryKey long pour votre id CustomLabel:

@Persistent(valueStrategy=IdGeneratorStrategy.IDENTITY) 
@PrimaryKey 
private Long id; 
+0

Juste une note: la clé primaire non nécessaire doit être de type 'Long'. – naXa

Questions connexes