Skip to content

Working with objects

ccapndave edited this page Feb 26, 2011 · 14 revisions

This section of the documentation will explain how to work with entities (objects) in Flextrine. Specifically we will talk about how to load, save, update and delete objects with Flextrine.

Where's my CRUD?

Many client/server systems for reading and writing follow the CRUD paradigm (Create, Read, Update, Delete) as it maps neatly to SQL and generally allows for clean row based operations on the database. Unfortunately the simple CRUD approach starts to become more complex if you want to represent a row with an object, and can end up very complicated indeed once you have relationships between those objects.

An ORM system like Flextrine is built from the ground up to work with objects instead of rows. In fact, the general idea is that from the perspective of your application there are no tables, rows or columns, only stores of objects. The ORM system takes care of translating operations on your objects into SQL calls, and results from SQL calls back into objects.

Transactional write-behind

Flextrine and Doctrine employ a pattern called 'Transactional write-behind'. This means that any write operations (i.e. operations that will cause a change in the database) are queued up until the command is given to actually apply them. This is especially valuable for an asynchronous client/server system like Flextrine as server calls are relatively expensive. The queue is executed using the em.flush() method, or the queue can be abandoned and entities returned to their original state using em.rollback(). See the Flush and rollback chapter for more details.

Persisting entities

Persisting is the ORM equivalent of Create.

An entity can be made persistent using the persist method of EntityManager. This immediately adds the entity to the appropriate EntityRepository. Note that the object's primary key will be empty until a successful flush() call, at which point it will automatically get filled in by Flextrine.

Only auto-generated primary key strategies are currently supported by Flextrine.

// This creates a NEW doctor
var doc:Doctor = new Doctor();

// This makes the doctor MANAGED, and marks it to be saved to the database on the next flush()
em.persist(doc);

// Add the doctor to the database
em.flush();

The semantics of the persist operation, applied on an entity X, are as follows:

  • If X is a NEW entity, it becomes MANAGED. The entity X will be entered into the database as a result of the flush operation.
  • If X is a pre-existing MANAGED entity, it is ignored by the persist operation.
  • If X is a REMOVED entity, it becomes MANAGED.
  • If X is a DETACHED entity, an exception will be thrown.

Removing entities

Removing is the ORM equivalent of Delete.

An entity is removed using the remove method of EntityManager. This immediately removes the entity from the appropriate EntityRepository. The entity will be removed from the database on the next flush().

// This makes the doctor REMOVED, and marks it to be deleted from the database on the next flush()
em.remove(doc);

// Remove the doctor from the database
em.flush();

The semantics of the remove operation, applied to an entity X are as follows:

  • If X is a NEW entity, it is ignored by the remove operation.
  • If X is a MANAGED entity, the remove operation causes it to become REMOVED.
  • If X is a DETACHED entity, an exception will be thrown.
  • If X is a REMOVED entity, it is ignored by the remove operation.

Updating entities

Once an entity is MANAGED (either because it has been loaded from the database or persisted) Flextrine will automatically watch its properties and associations for changes. This means that you don't need to do anything explicit to update an entity, except to call flush() when you want to save it.

// Change a property on the MANAGED doctor
doc.name = "Dr Different Name";

// Save changes to the database
em.flush();

Loading an entity by primary key

A single entity can be loaded from the database using the load() method. This is a direct wrapper for the Doctrine 2 find() operation. It is used to load a single entity by its primary key.

// Load the doctor with primary key of 1
var asyncToken:AsyncToken = em.getRepository(Doctor).load(1);

// A shortcut for the same operation
var asyncToken:AsyncToken = em.load(Doctor, 1);

Loading an entity by simple conditions

A single entity can be loaded from the database using the loadBy() method. This is a direct wrapper for the Doctrine 2 findBy() operation. It is used to load a selection of entities by a simple condition.

// Load all doctors with name "Dr Dave"
var asyncToken:AsyncToken = em.getRepository(Doctor).loadBy( { name: "Dr Dave" } );

// A shortcut for the same operation
var asyncToken:AsyncToken = em.loadBy(Doctor, { name: "Dr Dave" } );

If you are only searching for a single entity matching the simple conditions Flextrine provides a loadOneBy method:

// Load the first doctor with name "Dr Dave"
var asyncToken:AsyncToken = em.getRepository(Doctor).loadOneBy( { name: "Dr Dave" } );

// A shortcut for the same operation
var asyncToken:AsyncToken = em.loadOneBy(Doctor, { name: "Dr Dave" } );

Loading all entities

All entities of a particular class can be loaded using loadAll().

// Load all doctors
var asyncToken:AsyncToken = em.getRepository(Doctor).loadAll();

// A shortcut for the same operation
var asyncToken:AsyncToken = em.loadAll(Doctor);

Querying entities

For more complicated selections, entities can be queried using DQL select statements. See Complex queries and DQL for more details.

Clone this wiki locally