Search code examples
google-app-enginemany-to-manyentity-relationshipjdo

Object isnt saved for Unowned Many to Many relation


I have an unowned Many to Many relationship setup in JDO by adding the List in both the Persistence Capable objects. For the sake of explaining my problem lets call these two entities with .

EntityA and EntityB

Now, when i have a new Object of EntityB to be attached to the Object of EntityA, i append that Key to the EntityA object and call makePersistent on it, which saves the object. I verified that by printing it on the console.

Since, this is a Many to Many relation, i have to do the same on the other end of the relation as well. So, i fetch all the objects of EntityB which are referred by EntityA using select from " + clazz.getName()+ " where :keys.contains(key) and passing it the List of Keys which are present in Object of EntityA.

The problem that i encounter is, the objects returned back are Hollow, and hence they dont get saved into the datastore even if i append the EntityA keys to the fetched objects.

I am a newbie in JDO and GAE, and have been facing this problem since yesterday. Can someone please shed some light on this? I can provide sample code if needed too.


Solution

  • Here is the code

    @PersistenceCapable
    public class Objective {
    @PrimaryKey
    @Persistent(valueStrategy = IdGeneratorStrategy.IDENTITY)
    private Key key;
    @Persistent
    private boolean active;
    @Persistent
    private int corporate;
    @Persistent
    private String nameOfObjective;
    @Persistent
    private String shortDescription;
    @Persistent
    private int status;
    
    @Persistent
    private List<Key> scoreCardKeys; //List of Keys of Scorecards.
    
    
    @PersistenceCapable
    public class Scorecard {
    
    @PrimaryKey
    @Persistent(valueStrategy = IdGeneratorStrategy.IDENTITY)
    private Key key;
    
    @Persistent
    private boolean active;
    @Persistent
    private int corporate; // synonymous to being public 
    @Persistent
    private Date creationDate;
    @Persistent
    private String nameOfScorecard;
    @Persistent
    private String shortDescription;
    
    @Persistent
    private Key createdUserKey;
    
    @Persistent
    private List<Key> objectiveKeys; // List of Keys of Objectives
    

    Objective and Scorecard entities are in an unowned Many to Many relation

    Here is the processor method which will update a Scorecard.

    public ScoreCardRepresentation updateScoreCard(ScoreCardRepresentation scoreCardRepresentation) {
        Scorecard scoreCard = scoreCardTransformer
                .transformRtoEForSave(scoreCardRepresentation);
    
        scoreCard.setCreationDate(new Date());
    
        Scorecard updatedScoreCard = scoreCardDAO.saveScoreCard(scoreCard); /*     Update the scorecard, this already has the list of Key of Objectives in it, Hence blindly save it. */
    
    /* Update the Key of the scorecard in the Objectives too */       
    updateRelatedObjectivesToScoreCard(scoreCardRepresentation,updatedScoreCard);
    
    
    
    
    private void updateRelatedObjectivesToScoreCard(
            ScoreCardRepresentation scoreCardRepresentation,
            Scorecard updatedScoreCard) {
    List<String> addedObjectivesIds =  scoreCardRepresentation.getAddedObjectiveKeys();
    List<String> deletedObjectivesIds =  scoreCardRepresentation.getRemovedObjectiveKeys();
    
        // Add ScoreCard to the newly added Objectives
        if(addedObjectivesIds != null && addedObjectivesIds.size()>0){
    
    Scorecard sc = scoreCardDAO.findScoreCardById(Scorecard.class, updatedScoreCard.getKey());
            List<Key> objKeys = sc.getObjectiveKeys();
    
            List<Objective> objectives = objectiveDAO.findObjectivesByKeys(Objective.class,objKeys);
    

    // This uses the query select from " + clazz.getName()+ " where :keys.contains(key)

            for(Objective obj : objectives){
                List<Key> scoreCardKeys = obj.getScoreCardKeys();
                if(scoreCardKeys != null){
                    scoreCardKeys.add(sc.getKey());
                } else { 
                    scoreCardKeys = new ArrayList<Key>();
                    scoreCardKeys.add(sc.getKey());
                }
                obj.setScoreCardKeys(scoreCardKeys);
                Objective updatedObjective = objectiveDAO.saveObjective(obj);
                System.out.println(new ObjectiveProcessor().viewObjective(KeyFactory.keyToString(obj.getKey())));
            }
        }
    
        //Remove Scorecard entries from Objective. 
        if(deletedObjectivesIds != null && deletedObjectivesIds.size()>0){
            List<Objective> objectives = objectiveDAO.findObjectivesByIds(Objective.class,deletedObjectivesIds);
            for(Objective obj : objectives){
                List<Key> scoreCardKeys = obj.getScoreCardKeys();
                if(scoreCardKeys != null){
                    scoreCardKeys.remove(updatedScoreCard.getKey());
                } 
                obj.setScoreCardKeys(scoreCardKeys);
            }
        }
    }
    

    All i have been able to realise is that when i get back the Objectives using **findObjectivesByKeys** i am getting back hollow objects, so i have to call makeTransient on them to enable them for persistence, else they just ignore the makePersistent method call.