Skip to content

Eager and lazy loading

ccapndave edited this page Jun 16, 2011 · 2 revisions

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

configuration.fetchMode = FetchMode.EAGER;

By default Flextrine loads all associations in FetchMode.EAGER, 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.

What 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!

Here are some reasons that you should use FetchMode.EAGER:

  • 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!

And here are some reasons why you shouldn't use FetchMode.EAGER:

  • If you have bi-directional relationships between your entities and are not careful it is quite easy to load the entire database when just trying to load a single entity.
  • FetchMode.EAGER encourages the developer to only load data rarely; if the data is being changed by other users this may result in the application not having up-to-date entities.

As a general rule of thumb if you have a simple application which doesn't have massive amounts of data, and aren't using a lot of bi-directional relationships FetchMode.EAGER will work fine, and is easier to use.

However, for any more complicated RIA project FetchMode.EAGER will not be appropriate.

Lazy loading

configuration.fetchMode = FetchMode.LAZY;

FetchMode.LAZY is the exact opposite of FetchMode.EAGER. In FetchMode.LAZY 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 all its associations and collections containing placeholders, but no data.

Note that even if the configuration fetchMode is EAGER, you can still specify a different 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
}

You can require multiple collections with a single calls:

em.requireMany(tree, [ "branches", "birds", "gardeners" ], onStuffLoaded);

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

Lazy loading respects databinding, and you can bind components to entities or collections that have not yet been loaded. 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. Flextrine also provides [on-demand loading] so often you don't need even need to use requireOne or requireMany!

Note that where possible Flextrine will automatically fill in lazy entities when they are loaded as associations from other entities:

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.

Clone this wiki locally