5

I am using the local-development version of App Engine's JDO implementation. When I query an object that has contains other objects as embedded fields, the embedded fields are returned as null.

For example, lets say this is the main object that I am persisting:

@PersistenceCapable
public class Branch {

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

    @Persistent
    private String name;

    @Persistent
    private Address address;

            ...
}

and this my embedded object:

@PersistenceCapable(embeddedOnly="true")
public class Address {

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

    @Persistent
    private String street;

    @Persistent
    private String city;

            ...
}

the following code does not retrieve the embedded object:

    PersistenceManager pm = MyPersistenceManagerFactory.get().getPersistenceManager();

    Branch branch = null;
    try {
        branch = pm.getObjectById(Branch.class, branchId);
    }
    catch (JDOObjectNotFoundException onfe) {
        // not found
    }
    catch (Exception e) {
        // failed
    }
    finally {
        pm.close();
    }

Does anyone have a solution for this? How can I retrieve the Branch object along with its embedded Address field?

DataNucleus
  • 15,497
  • 3
  • 32
  • 37
Chania
  • 307
  • 3
  • 14

1 Answers1

6

I had a similar problem and found that embedded fields are not included in the default fetch group. To have the required field loaded you will either have to call the getter for it before closing the persistence manager or set the fetch group to load all fields.

This means the following...

branch = pm.getObjectById(Branch.class, branchId);
pm.close();
branch.getAddress();  // this is null

branch = pm.getObjectById(Branch.class, branchId);
branch.getAddress();  // this is not null
pm.close();
branch.getAddress();  // neither is this

So, you would need to change your code as follows:

Branch branch = null;
try {
    branch = pm.getObjectById(Branch.class, branchId);
    branch.getAddress();
}
catch (JDOObjectNotFoundException onfe) {
    // not found
}
catch (Exception e) {
    // failed
}
finally {
    pm.close();
}

Alternatively, you can set your fetch group to include all fields as follows...

pm.getFetchPlan().setGroup(FetchGroup.ALL);
branch = pm.getObjectById(Branch.class, branchId);
pm.close();
branch.getAddress();  // this is not null
Cengiz
  • 1,050
  • 1
  • 13
  • 19
  • Thanks for the prompt answer! I will test this and let you know if it works. – Chania May 08 '12 at 06:58
  • If a field is in the active fetch group then it obviously ought to be fetched. If you say it isn't then why not provide a simple testcase and report it at http://code.google.com/p/datanucleus-appengine/issues/list Not reporting it likely means that nobody involved in the project will know about it – DataNucleus May 09 '12 at 17:55
  • I am not sure if this is a bug or a part of the JDO specification. I remember reading somewhere that lazy-loading of embedded fields was in the JDO specs, but I can't find it now. – Cengiz May 11 '12 at 20:04
  • Any field can be lazy or eager, when marked as such. Either way, my previous comment stands – DataNucleus May 16 '12 at 15:07