My favorites | Sign in
Project Home Downloads Wiki Issues Source
Search
for
Functions  
How to use the Function interface in Google Collections to transform lists of persistent instances.
Updated Mar 27, 2012

Introduction

When iterating through long lists of persistent data, it is possible to avoid launching n + 1 queries by using Functions to transform entities into collections of Keys that can be retrieved using a single batch get() call. This feature can be used to retrieve parent instances or foreign key entities, and they work with collections or PagedList contents.

This is specially important for cacheable entities, since all referred entities can be loaded into the cache with a single invocation.

Parent entities

To retrieve a list of parent keys from the children keys:

List<Key> childKeys = entityManager.find(entityManager.createQuery(Child.class).keysOnly());
List<Key> rootKeys = Collections2.transform(childKeys, new KeyToParentKeyFunction());

To retrieve a list of parent instances from the children data:

List<Child> children = entityManager.find(entityManager.createQuery(Child.class));
List<Key> rootKeys = Collections2.transform(children, new EntityToParentKeyFunction(Child.class));
List<Root> roots = entityManager.get(rootKeys);

Save space for your relationships by storing Set<Long> instead of Set<Key>

Set<Long> userIds = user.getFriends();
Collection<Key> userKeys = Collections2.transform(userIds, new IdToKeyFunction(User.class));
Collection<User> users = entityManager.get(userKeys);

Transform back

CompositeFunction<User, Long> func = new CompositeFunction(
	new EntityToKeyFunction(User.class), 
	new KeyToIdFunction()
);
user.setFriends(Collections2.transform(users, func));

A list of available functions can be found at the SimpleDS javadoc.

Because of performance, you will find no EntityToParentEntityFunction or similar. Instead, you are expected to convert the list of entities into a collection of Keys and then retrieve with a single call to entityManager.get(keys).

Notice that this requires only two invocations to the datastore, no matter the number of entities. When combined with cacheable entities, memcache will be invoked first.

Foreign key entities

Entities can also be retrieved using foreign keys. Suppose you have a siblingKey attribute:

List<Child> children = entityManager.find(entityManager.createQuery(Child.class));
List<Key> siblingKeys = Collections2.transform(children, new EntityToPropertyFunction<Child, Key>(Child.class, "siblingKey"));
List<Child> siblings = entityManager.get(siblingKeys);

Paged lists

Transformations can also be applied with paged results:

PagedList<Child> children = entityManager.findPaged(PagedQueryFactory.create(Child.class));
PagedList<Key> siblingKeys = children.transform(new EntityToPropertyFunction<Child, Key>(Child.class, "siblingKey"));
PagedList<Child> siblings = siblingKeys.transformToEntities();

Sign in to add a comment
Powered by Google Project Hosting