My favorites | Sign in
Project Home
Search
for
LazyLoading  
Updated Jun 16, 2010 by devdavek@gmail.com

Loading associations

Keep in mind the following entity graph:

  • A garden has many trees, many trees have one garden
  • A tree has many branches, many branches have one tree
  • A branch has many leaves, many leaves have one branch

Eager loading

By default Flextrine loads all associations in eager mode, which means that when you load an entity from the server, the entity and all associated entities will be retrieved. This makes things very easy for you as you know that the whole object tree will be available for your use.

This means that getting any entity in a garden will retrieve every tree, branch and leaf in that garden. Doing a loadAll() on Garden will retrieve every garden, tree, branch and leaf in the entire database!

Eager loading is obviously not going to be particularly efficient, but there are some things to bear in mind:

  • Flex works asyncronously which means that every load involves a client/server call. Although eager loading entities may involve retrieving some entities that you don't need right away, one big load might result in better performance for your application that continuously doing client/server calls.
  • Doctrine is quite clever when eager loading entities and performs a minimum of SQL queries to get its data, so the performance hit from the database is not necessarily going to be as costly as you might expect, even when getting large numbers of entities.
  • Flextrine communicates with the server in compressed binary format (AMF), so lots of entities doesn't necessarily mean massive bandwidth.
  • Having all your entities eager loaded into the repositories makes Flextrine code simpler to write!

Having said all that, sometimes eager loading will simply not be appropriate.

Lazy loading

Lazy loading is the exact opposite of eager loading. In lazy loading mode you will get only the entities you request and nothing more. Therefore if you were to load a Tree entity, that's all that you would get back - a single Tree entity with garden unset, and branches containing an empty ArrayCollection.

To activate lazy loading use the fetchMode configuration option when setting up your EntityManager.

var configuration:Configuration = new Configuration();
configuration.gateway = "http://localhost/myflextrineproject/gateway.php";
configuration.fetchMode = FetchMode.LAZY;
em.setConfiguration(configuration);

You can also specify the fetchMode for a particular request.

em.getRepository(Tree).loadAll(FetchMode.LAZY);

Most server side ORM solutions use a Proxy pattern to transparently load associations when they are accessed, but unfortunately in asyncronous AS3 we don't have that luxury. Therefore when you want to get an unloaded association in Flextrine you need to explicitly request it.

For single values associations (e.g. tree.garden) you use the requireOne method.

em.requireOne(tree.garden, onGardenLoaded);

function onGardenLoaded():void {
	// Now we are guaranteed that branch.garden contains the garden
}

Note that if tree.garden happened to already be loaded when you call requireOne, the onGardenLoaded method would be called instantly.

Requiring collections is similar:

em.requireMany(tree, "branches", onBranchesLoaded);

function onBranchesLoaded():void {
	// Now we are guaranteed that tree.branches contains all the branches on the tree
}

As with requireOne, if tree.branches is pre-loaded when you call requireMany, the onBranchesLoaded method is called instantly.

Databinding and lazy loading

Lazy loading respects databinding, and you can bind components to entities or collections that have not yet been loaded. Look at the LazyGardenExample in tests/examples to see databinding and lazy loading in action. Making clever use of databinding and lazy loading can often allow you to get away without having to implement a handler on requireOne or requireMany.

Automatic association linking

Where possible Flextrine will automatically fill in lazy entities when they are loaded, even if you don't specifically use require.

em.getRepository(Garden).loadAll();
em.getRepostiory(Tree).loadAll();

When the load is complete every garden.trees will be populated with the appropriate tree collection, and every tree.garden will refer to the appropriate garden.

Loading specific associations

Flextrine will soon support a method of allowing you to specify exactly which associations you want to load through DQL fetch joins. This can be useful when you know exactly which associations you need at the time of the request or if you need something in between eager and lazy loading.

Pitfalls

Lazy loading is a powerful feature, but it does make your code significantly more complicated. Here are some things to look out for:

  • If an entity is lazy loaded through an association and that entity is already in the repository the existing entity will remain unchanged. That means that if you have loaded a garden and a tree and then you reload the tree with fetch mode LAZY, the garden will not change. If it so happens that the tree was uprooted and moved to a different garden since your last load your repository will still contain an out of date entity.
  • Lazy loading is very complicated, and is likely to be the least stable feature of Flextrine at present! If you spot any bugs please log them in the Issues tab.

Sign in to add a comment
Powered by Google Project Hosting