ColdFusion 9.0 Resources |
Advanced mappingThis section covers some of the advanced mappings. Collection MappingCollection mapping is similar to a one-to-many relationship mapping. However, in collection mapping, you have a collection of values instead of a collection of persistent target objects. Consider the Artist-Art tables. If you want each Artist object to contain an array of artwork names instead of artwork objects, collection mapping should be used. To define collection mapping in the CFC, use fieldtype="collection" in the cfproperty tag. The collection can either be Array or Struct. ArraySyntaxname="field_name" fieldtype="collection" type="array" table="table_name" fkcolumn="foreign_key_column_name" elementtype="ormtype" elementColumn="column_name from the link table that should be used for populating" orderby="order by string" lazy = "true|[false]" readonly="true|[false]" optimisticlock="[true]|false" batchsize="batch size"> ExampleIf each Artist object contains an array of artwork names instead of artwork objects, this mapping can be defined in Artist.cfc as: <cfproperty name="artNames" fieldtype="collection" type="array" table="ART" fkcolumn="ARTISTID" elementcolumn="ARTNAME" elementtype="string"> Attribute
StructSyntax<cfproperty name="field_name" fieldtype="collection" type="struct" table="table_name" fkcolumn="foreign_key_column_name" structkeycolumn="column in the target table to be used as key in the struct" structkeytype="ormtype of the key in the struct" elementtype="ormtype of the valye in the struct" elementColumn="column name from the table that should be used in value of struct" orderby="order by string" lazy = "[true]|false" readonly="true|[false]" optimisticlock="[true]|false" batchsize="batch size">
Inheritance mappingIf the object you need to persist has a hierarchy, the CFCs of that object hierarchy need to be mapped to the relational tables such that the entire hierarchy is persisted. There are multiple strategies followed for inheritance mapping:
Table per hierarchyIn this model, the object hierarchy is persisted in a single table. This table includes columns for all the properties of all the CFCs in the hierarchy. The concrete subclass represented by a row is identified based on the value of the discriminator column. In this strategy, all the CFCs of the hierarchy must have the same table name. Note: If the discriminator column and discriminator value is not
specified, a default discriminator column name and value is picked
up.
Example The following example demonstrates an implementation of table per hierarchy: In the preceding figure, discriminatorColumn is PaymentType. Depending on the values of PaymentType whether it is credit card or check, the row is represented as a CreditCardpayment or checkPayment object respectively. The following example illustrates how you can model the table per hierarchy: Payment.cfc (parent class) <cfcomponent persistent="true" table="Payment" discriminatorColumn="paymentType"> <cfproperty name="id"> <cfproperty name="amount"> </cfcomponent> CreditCardPayment.cfc <cfcomponent persistent="true" extends="Payment" table="Payment" discriminatorValue="CCard"> <cfproperty name="cardNo"> <cfproperty name="cardType"> </cfcomponent> CheckPayment.cfc <cfcomponent persistent="true" extends="Payment" table="Payment" discriminatorValue="check"> <cfproperty name="checkNo"> <cfproperty name="bankName"> <cfproperty name="city"> </cfcomponent> Table per subclass without discriminatorIn this model, there are separate tables for each class in the hierarchy and these tables are joined by a primary key. When the object is persisted, properties of the parent component are stored in the parent table and the remaining properties are stored in the child table. In the preceding figure, the tables are joined by join column paymentId. You can model the tables as follows: Payment.cfc <cfcomponent persistent="true" table="Payment"> <cfproperty name="paymentId"> <cfproperty name="amount"> </cfcomponent> CreditCardpayment.cfc <cfcomponent persistent="true" extends="Payment" table="CreditCardPayment" joinColumn="paymentId"> <cfproperty name="cardNo"> <cfproperty name="cardType"> </cfcomponent> CheckPayment.cfc <cfcomponent persistent="true" extends="Payment" table="CheckPayment" joinColumn="paymentId"> <cfproperty name="checkNo"> <cfproperty name="bankName"> <cfproperty name="city"> </cfcomponent> When an object of type CreditCardPayment is persisted, the property amount is stored in the payment table and the properties cardNo and cardType are stored in the CreditCardPayment table. The primary key of the CreditCardPayment remains the same as the primary key of the Payment table. Table per subclass with discriminatorThis model is similar to the table per subclass without discriminator strategy except that there is a discriminator column in the parent table. In addition, the child components has a disciminatorValue attribute in the cfcomponent tag. The following example demonstrates the table per subclass with discriminator attribute: Payment.cfc <cfcomponent persistent="true" table="Payment" discriminatorColumn="paymentType"> <cfproperty name="paymentId"> <cfproperty name="amount"> </cfcomponent> CreditCardPayment.cfc <cfcomponent persistent="true" extends="Payment" table="CreditCardPayment" joinColumn="paymentId" discriminatorValue="CCard"> <cfproperty name="cardNo"> <cfproperty name="cardType"> </cfcomponent> CheckPayment.cfc <cfcomponent persistent="true" extends="Payment" table="CheckPayment" joinColumn="paymentId" discriminatorValue="Check"> <cfproperty name="checkNo"> <cfproperty name="bankName"> <cfproperty name="city"> </cfcomponent> When an object of type CreditCardPayment is persisted, the property amount is stored in the payment table and the properties cardNo and cardType are stored in the CreditCardPayment table. The primary key of CreditCardPayment remains the same as the primary key of the Payment table. The value of PaymentType is the value of disciminatorColumn attribute of the respective object. Embedded mappingThis mapping is used when a CFC has an embedded object which also needs to be persisted along with the parent's data. The CFC of the embedded object must have the attribute embedded set to "true" on the cfcomponent tag. Important: The embedded object
cannot be a persistent object. This feature is supported only when
the hibernate mapping is explicitly defined in the hibernate mapping
file (.hbmxml files).
Name.cfc embedded in Employee.cfc The diagram shows two CFCs Employee and Name where EmployeeName field of the Employee.cfc is an object of Name.cfc. In the database, both these objects are persisted in the Employee table as a single row. Name object itself does not have its own identity. This mapping can be modeled as follows: name.cfc <cfcomponent embedded="true"> <cfproperty name="FirstName"> <cfproperty name="LastName"> <cfproperty name=" TitleOfCourtesy"> </cfcomponent> employee.cfc <cfcomponent persistent="true"> <cfproperty name="EmployeeID"> <cfproperty name="EmployeeName"> <cfproperty name="Designation"> </cfcomponent> employee.hbmxml <hibernate-mapping > <class name="cfc:Employee" table="Employees"> <id name="EmployeeID" type="integer" column="EmployeeID"> <generator class="native"/> </id> <component name="NameComponent" class="cfc:Name"> <property name="LastName" type="string" column="LastName"/> <property name="FirstName" type="string" column="FirstName"/> <property name="TitleOfCourtesy" type="string" column="TitleOfCourtesy"/> </component> <property name="Designation" type="string" column="Designation"/> </class> </hibernate-mapping> For more details on component mapping in hibernate, see Component Mapping in Hibernate Reference Guide. Join mapping in a CFCJoin mapping is used to map the properties of one CFC to several tables. In this case, tables are joined using a join column. For example, consider a case where the Employee and Address tables, are mapped to a single CFC Employees. Therefore, the employee.cfc has some fields, which are persisted in Employee table and some fields that are persisted in Address table. The attributes joincolumn and table should be specified for those fields that need to be persisted in Address table. In this case, table would be Address and joinColumn would be AddressID. Following is a sample employee.cfc Employee.cfc <cfcomponent persistent="true"> <cfproperty name="id"> <cfproperty name="name"> <cfproperty name="houseno" column="houseno" table="Address" joincolumn="addressId"> <cfproperty name="street" table="Address" joincolumn="addressId"> <cfproperty name="city" table="Address" joincolumn="addressId"> <cfproperty name="country" table="Address" joincolumn="addressId"> </cfcomponent> Define the ORM mapping in the Hibernate mapping fileColdFusion can also use the standard Hibernate Mapping XML file to define the mapping between the object and the database. You can use both Java classes and CFCs in Hibernate mapping. For a complete description of hibernate mapping, see www.hibernate.org/hib_docs/reference/en/html/mapping.html. Note the following points when using Hibernate mapping files.
The following is an example of Hibernate mapping:
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"> <hibernate-mapping> <class lazy="true" name="cfc:artGallery.Art" schema="APP" table="Art"> <id name="artid" type="int"> <column length="10" name="ARTID"/> <generator class="identity"/> </id> <property name="artname" type="string"> <column length="50" name="ARTNAME"/> </property> <property name="price" type="java.math.BigDecimal"> <column length="19" name="PRICE"/> </property> <property name="largeimage" type="string"> <column length="30" name="LARGEIMAGE"/> </property> <property name="mediaid" type="int"> <column length="10" name="MEDIAID"/> </property> <property name="issold" type="boolean"> <column length="5" name="ISSOLD"/> </property> <many-to-one class="cfc:artGallery.Artists" column="artistid" name="artist"/> </class> </hibernate-mapping> |