ColdFusion 9 extends offline application support to the client side of the application by letting you code ActionScript elements on the client side. The data that is exchanged and synchronized on the client side is managed through persistent objects in the local or offline database.
Managing relationships
The ActionScript persistent framework lets you define the following relationship types between two persistent objects.
- one-to-one
- one-to-many
- many-to-one
- many-to-many
To understand how the persistent framework handles relationships, let us consider an example of the Employee and Department objects in a database.
If you do not specify attribute values, the default values are taken as follows:
- The default table name is the class name.
- The default value for columnDefinition is the ActionScript type of the field.
- The default value for referencedColumnName is the primary key of the target entity.
- The default value for targetEntity is the ActionScript type of the referring field.
In case you are using ORM CFCs, the remotingFetch attribute in the <cfproperty> tag is set to false by default for all relationships. You must set this attribute to true to retrieve data on the client side. |
One-to-one relationship
Consider a one-to-one relationship where one employee belongs to a single department. You can use code like the following to define a one-to-one mapping between the Department and Employee objects with DEPTID as the foreign key column name.
[Entity] |
The JoinColumn}}tag specifies the foreign key column and all the attributes of the column tag. Do not specify {{JoinColumn for both the entities in the relationship. For example, in the one-to-one relationship between the Department and Employee objects, specify {{JoinColumn}}only for one of the entities depending on the direction of the relationship.
referencedColumnName specifies the primary key column that it refers to. Class indicates the target entity, which is Department in this example.
The default fetchType value is EAGER. See Lazy loading and fetch type below for information on fetch types.
One-to-many relationship
Consider a one-to-many relationship where one employee belongs to many departments. You can use code like the following to define a one-to-many mapping between the Department and Employee objects.
public class Employee |
There is no column specified in the Employee table but refers to the field in the Department entity that points to the Employee entity.
The default fetchType value is LAZY. See Lazy loading and fetch type below for information on fetch types
Many-to-one relationship
Consider a many-to-one relationship where many employees belong to a single department. You can use code like the following to define a many-to-one mapping between the Department and Employee objects.
public class Employee |
The default fetchType value is EAGER. See Lazy loading and fetch type below for information on fetch types
Many-to-many relationship
Consider a many-to-many relationship where many employees belong to many departments. You can use code like the following to define a many-to-many mapping between the Department and Employee objects.
public class Employee |
The default fetchType value is LAZY. See Lazy loading and fetch type below for information on fetch types.
For a many-to-many relationship, you specify metadata like the following only on one of the entities and not both.
[JoinTable(name="ORDER_PRODUCT")] |
The JoinColumn tag specifies the foreign key column and all the attributes of the column tag. The InverseJoinColumn tag specifies the reference to the joining entity in the JoinTable tag. In this example, join table "EMP_DEPT" has a column named "DEPID", which refers to the "DEPTID" column of the Department table.
The JoinTable tag defines the join table for the many-to-many relationship specifying the join column and inverse join column. In this example, a join table named "EMP_DEPT" is created in the Offline SQLite DB with a many-to-many relationship between the Employee and Department tables.
Lazy loading and fetch type
The ActionScript persistent framework supports lazy loading although it may not be as intuitive because of the asynchronous connection with the database.
The fetch type EAGER or LAZY determines the fetch type for the relationship that is loaded. An EAGER fetch type loads the relationship and fetches data when the call is first made. A LAZY fetch type loads the relationship and fetches data only when an explicit fetch call is made. The default value for the fetch type is EAGER and the default value for ignoreLazyLoad is false.
When you specify fetchType="EAGER" at the class-definition level, the loadByPk function always loads the related object, irrespective of the value you specify for the ignoreLazyLoad parameter.
When you specify fetchType="LAZY" at the class-definition level, you can have two possibilities:
- When you specify the ignoreLazyLoad parameter
as true, the related object is also loaded. For
example, if you have two related objects Address and Customer, and
specify loadByPK(Customer,{id:3},true), the Address
object is also loaded. - When you do not specify any value for the ignoreLazyLoad parameter,
it takes the default value that is false, and the
related object is not loaded. For example, if you have two related
objects Address and Customer, and specify loadByPK(Customer,{id:3}),
the Address object is not loaded.
Cascading options
Cascading lets you specify the operations to be cascaded from the parent object to the associated object. The supported operations are INSERT, UPDATE, and DELETE. The cascadeType attribute lets you set any of the following values.
- ALL If The source entity is inserted, updated, or deleted, the target entity is also inserted, updated, or deleted.
- PERSIST If The source entity is inserted or updated, the target entity is also inserted or updated.
REMOVE If The source entity is deleted, the target entity is also deleted.
The one-to-one, one-to-many, many-to-one, and many-to-many relationships are all supported by cascading. You can use code like the following to specify the cascading options:ManyToMany(cascadeType="ALL or PERSIST or REMOVE")
If you do not specify the cascadeType option, only the source entity is persisted or updated.
When you specify cascadeType='ALL or REMOVE'}}to remove the parent object and the associated child objects, load the parent object using {{load***() method and pass it through session.remove(parentObj). If you do not use this method of loading, only the parent object gets deleted from SQLite database and the child objects remain.
Note: If you have enabled lazy loading by specifying fetchType='LAZY' at the entity level, when you load a parent object using load**() method, the child objects are not loaded. When you specify cascadeType='ALL or REMOVE' and try to delete the parent object by passing it through session.remove(parentObj), it does not delete the child objects. To overcome this limitation, use the load**() method with ignorelazyloading='true'. |