Vishwanath Vishwanath - 3 months ago 7
Java Question

Lazily loaded embedded objects are not fetched completely GAE datastore

I am facing weird problem with Embedded entity inside my parent entity.

Following is the code

Below is my child entity.

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

private String groupId;
private String fromUserId;
private String toUserId;
private double amount;
}


It's embedded inside group.

@PersistenceCapable(identityType = IdentityType.APPLICATION)
public class Group {


@PrimaryKey
@Persistent(valueStrategy = IdGeneratorStrategy.IDENTITY)
@Extension(vendorName="datanucleus", key="gae.encoded-pk", value="true")
private String groupId;


private String groupName;
private String groupType;
private String ownerId;

@Persistent(defaultFetchGroup = "true")
private List<IOU> iouList;
}


I am doing a bit dirty work while storing them, I don't know if that's the problem.
I store them as follows.

group = mgr.makePersistent(group);

ArrayList<IOU> alIOU = this.generateIOUEntries(alTotalMembers, group);
group.setIouList(alIOU);
group = mgr.makePersistent(group);


Above is done, since I need autogenerated groupId inside my IOU.

Now the problem is when I try to fetch my group. List of iou contains only amount as property.

{
"groupId" : "agdmZW0tZGV2cgsLEgVHcm91cBgEDA",
"groupName" : "Test",
"ownerId" : "agdmZW0tZGV2cgoLEgRVc2VyGAEM",
"members" : [ {
"userId" : "agdmZW0tZGV2cgoLEgRVc2VyGAIM",
}, {
"userId" : "agdmZW0tZGV2cgoLEgRVc2VyGAMM",
}, {
"userId" : "agdmZW0tZGV2cgoLEgRVc2VyGAEM",
} ],
"membersIdList" : [ "agdmZW0tZGV2cgoLEgRVc2VyGAIM", "agdmZW0tZGV2cgoLEgRVc2VyGAMM", "agdmZW0tZGV2cgoLEgRVc2VyGAEM" ],
"iouList" : [ {
"amount" : 0.0
}, {
"amount" : 0.0
}, {
"amount" : 0.0
} ]
}


Weird thing is that, if I restart the server. All values are fetched properly. I am new to this JDO world, so I tried various combinations of annotation but nothing helped. I am guessing this might be related to some caching technique which is flushed to DB when I stop the server.

fromUserId and toUserId are not fetched until I restart the server.
Correct output looks like this.

{
"groupId" : "agdmZW0tZGV2cgsLEgVHcm91cBgEDA",
"groupName" : "Test",
"ownerId" : "agdmZW0tZGV2cgoLEgRVc2VyGAEM",
"members" : [ {
"userId" : "agdmZW0tZGV2cgoLEgRVc2VyGAIM",
}, {
"userId" : "agdmZW0tZGV2cgoLEgRVc2VyGAMM",
}, {
"userId" : "agdmZW0tZGV2cgoLEgRVc2VyGAEM",
} ],
"membersIdList" : [ "agdmZW0tZGV2cgoLEgRVc2VyGAIM", "agdmZW0tZGV2cgoLEgRVc2VyGAMM", "agdmZW0tZGV2cgoLEgRVc2VyGAEM" ],
"iouList" : [ {
"fromUserId" : "agdmZW0tZGV2cgoLEgRVc2VyGAIM",
"toUserId" : "agdmZW0tZGV2cgoLEgRVc2VyGAMM",
"amount" : 0.0
}, {
"fromUserId" : "agdmZW0tZGV2cgoLEgRVc2VyGAIM",
"toUserId" : "agdmZW0tZGV2cgoLEgRVc2VyGAEM",
"amount" : 0.0
}, {
"fromUserId" : "agdmZW0tZGV2cgoLEgRVc2VyGAMM",
"toUserId" : "agdmZW0tZGV2cgoLEgRVc2VyGAEM",
"amount" : 0.0
} ]
}


Code to retrieve is as simple as following. To lazily load iouList I touch it by calling getIouList() on it.

Group group = mgr.getObjectById(Group.class, id);
group.getIouList()

Answer

I found answer to the problem.

Following question mentions about the same problem. One-to-Many relationship. Select objects from datastore

For now, I touched each IOU entry in the iouList to get them loaded.

Group group = mgr.getObjectById(Group.class, id);
group.getIouList()

for(IOU objIOU : group.getIouList()){
    objIOU.getFromUserId();
}

Above code loads each property of the IOU in list.

I am guessing that only amount was getting shown previously, since it being a primitive had value of zero and other properties were null, and nulls were excluded in the serialization while creating JSON.

I might try approach of using following annotation and update about same.

@Persistent(mappedBy = "restaurant",defaultFetchGroup = "true")
Comments