| <?xml version="1.0" encoding="ISO-8859-1"?> |
| <document> |
| <properties> |
| <title>OpenEJB CMP Mapping</title> |
| </properties> |
| |
| <body> |
| <title>OpenEJB CMP Mapping</title> |
| |
| <section title="Preface"> |
| |
| <p> |
| The OpenEJB CMP Container is no simple container. Unlike most CMP 1.1 |
| containers, which simply generate BMP code for you and cannot handle |
| complex object-to-relational (O/R) mapping, the OpenEJB CMP Container |
| does all of that and more. It supports very complicated O/R mapping |
| and can map an entity bean across several tables and dependent objects. |
| It also supports the OMG's Object Query Language (OQL) which gives your |
| ejbFind methods added power. |
| </p> |
| |
| <p> |
| All of this is done through the power of Castor JDO, a project that has been |
| developed since day one to be the most sophisticated CMP Container ever created. |
| Castor fulfills that role in spades and has become one of the most popular |
| object-to-relational and object-to-xml tools in the commercial or open source |
| world. |
| </p> |
| |
| <p>This document details the full syntax of Castor's O/R mapping ability, it is |
| not for the weak of heart. For a simple introduction to OpenEJB CMP and the |
| related Castor mapping.xml files, see this wonderful doc written by Jacek Laskowski, |
| <a href="cmp_entity_postgresql.xml">CMP Hello World.</a> |
| </p> |
| |
| <p>OpenEJB would like to thank the whole Castor team for their great work and to |
| <a href="mailto:ferret@frii.com">Bruce Snyder</a> for writing this very thorough |
| doc on the syntax of the mapping.xml file used for entity-to-relational mapping. |
| </p> |
| |
| </section> |
| |
| <section title="Introduction"> |
| <p> |
| Castor mapping files are used by the OpenEJB CMP Container to provide a mechanism |
| for binding a Java object model (an EntityBean and it's Java objects) to a |
| relational database model. This is usually referred to as object-to-relational |
| mapping (O/R mapping). O/R mapping bridges the gap between an object model and a |
| relational model. |
| </p> |
| |
| <p> |
| The following is a high-level example of a mapping file: |
| </p> |
| |
| <code> |
| <mapping> |
| <class> |
| <map-to /> |
| <field> |
| <sql /> |
| </field> |
| ... |
| </class> |
| </mapping> |
| </code> |
| |
| <p> |
| Each EntityBean and dependent Java object is represented by a <class> element |
| composed of attributes, a <map-to> element and <field> elements. The <map-to> element |
| contains a reference to the relational table to which the EntityBean maps. |
| Each <field> element represents either a public class variable or a the |
| variable's accessor/mutator methods (depending upon the mapping info). Each |
| <field> element is composed of attributes and one <sql> element. |
| The <sql> element represents the field in the relational table to which |
| the <field> element maps. |
| </p> |
| |
| </section> |
| |
| <section title="The Mapping File"> |
| |
| <section title="The <class> element "> |
| |
| <code> |
| <!ELEMENT class ( description?, cache-type?, map-to?, field+ )> |
| <!ATTLIST class |
| name ID #REQUIRED |
| extends IDREF #IMPLIED |
| depends IDREF #IMPLIED |
| auto-complete ( true |false ) "false" |
| identity CDATA #IMPLIED |
| access ( read-only | shared | exclusive | db-locked ) "shared" |
| key-generator IDREF #IMPLIED > |
| </code> |
| |
| |
| <p> |
| The <class> element contains all the information used to map a EntityBean |
| to a relational database. The content of <class> is mainly used to describe |
| the fields that will be mapped. |
| </p> |
| |
| <p> |
| Description of the attributes: |
| </p> |
| |
| <ul> |
| <li><b>name:</b> The fully qualified package name of the EntityBean or dependent Java object to map to.</li> |
| |
| <li><b>extends:</b> Should be used _only_ if this EntityBean or dependent Java object extends another Java |
| object for which mapping information is provided. It should _not_ be used if the |
| extended Java object is not referenced in the mapping file.</li> |
| |
| <li><b>depends:</b> For more information on this field, please see |
| <a href="http://castor.exolab.org/castor-one.html#Dependent-and-related-relationships"> |
| Dependent and related relationships</a>.</li> |
| |
| <li><b>identity:</b> For more information on this field, please see |
| <a href="http://castor.exolab.org/design-persist.html#Persistence">Design -> Persistence</a>.</li> |
| |
| <li><b>access:</b> For more information on this field, please see |
| <a href="http://castor.exolab.org/locking.html#Locking-Modes">Locking Modes</a>.</li> |
| |
| <li><b>key-generator</b>: For more information on this field, please see |
| <a href="http://castor.exolab.org/key-generator.html">KeyGen</a>.</li> |
| </ul> |
| |
| <p>Description of the elements:</p> |
| |
| <ul> |
| <li><b><description></b>: An optional description.</li> |
| |
| <li><b><cache-type></b>: For more information on this field please see |
| <a href="http://castor.exolab.org/long-transact.html#Bounded-dirty-checking">Bounded Dirty Checking</a> |
| and <a href="http://castor.exolab.org/castor-one.html#LRU-Cache">LRU Cache</a>.</li> |
| |
| <li><b><map-to></b>: Used to tell the CMP Container the name of the relational |
| table to which to map.</li> |
| |
| <li><b><field></b>: Zero or more <field> elements are used to describe properties |
| of each EntityBean or dependent Java object.</li> |
| </ul> |
| |
| </section> |
| |
| <section title="The <map-to> element"> |
| |
| <code> |
| <!ELEMENT map-to EMPTY> |
| <!ATTLIST map-to |
| table NMTOKEN #IMPLIED |
| xml NMTOKEN #IMPLIED |
| ns-uri NMTOKEN #IMPLIED |
| ns-prefix NMTOKEN #IMPLIED |
| ldap-dn NMTOKEN #IMPLIED |
| ldap-oc NMTOKEN #IMPLIED> |
| </code> |
| |
| <p><map-to> is used to specify the name of the item that should be associated |
| with the given EntityBean or dependent Java object. The <map-to> element is only used for the root |
| Java object.</p> |
| |
| <p>Description of the attributes:</p> |
| |
| <ul> |
| <li><b>table:</b> The name of the relational database table to which the |
| EntityBean or dependent Java object is associated.</li> |
| </ul> |
| |
| </section> |
| |
| |
| <section title="The <field> element"> |
| |
| <code> |
| <!ELEMENT field ( description?, sql?, xml?, ldap? )> |
| <!ATTLIST field |
| name NMTOKEN #REQUIRED |
| type NMTOKEN #IMPLIED |
| required ( true | false ) "false" |
| direct ( true | false ) "false" |
| lazy ( true | false ) "false" |
| transient ( true | false ) "false" |
| get-method NMTOKEN #IMPLIED |
| set-method NMTOKEN #IMPLIED |
| create-method NMTOKEN #IMPLIED |
| collection ( array | vector | hashtable | collection | set | map ) #IMPLIED> |
| </code> |
| |
| <p>The <field> element is used to describe a property of a EntityBean or dependent Java object. It provides:</p> |
| <ul> |
| <li>the object's identity ('name')</li> |
| <li>the object's type (inferred from 'type' and 'collection')</li> |
| <li>the object's access method (inferred from 'direct', 'get-method', 'set-method')</li> |
| </ul> |
| |
| <p>From this information, the CMP Container is able to access a given property in the EntityBean or dependent Java |
| object.</p> |
| |
| <p>In order to determine the signature that the CMP Container expects, there are two easy |
| rules to apply.</p> |
| |
| <p><b>1. Determine <type>.</b></p> |
| |
| <ul> |
| <li><p><b>If there is no 'collection' attribute</b>, the object type is the the value |
| of the 'type' attribute. The value of the type attribute can be a fully qualified Java |
| object like 'java.lang.String' or one of the allowed aliases:</p> |
| |
| <table border="1" cellpadding="4"> |
| <tr><th>short name</th><th>Primitive type?</th><th>Java Class</th></tr> |
| <tr><td>other</td><td>N</td><td>java.lang.Object</td></tr> |
| <tr><td>string</td><td>N</td><td>java.lang.String</td></tr> |
| <tr><td>integer</td><td>Y</td><td>java.lang.Integer.TYPE</td></tr> |
| <tr><td>long</td><td>Y</td><td>java.lang.Long.TYPE</td></tr> |
| <tr><td>boolean</td><td>Y</td><td>java.lang.Boolean.TYPE</td></tr> |
| <tr><td>double</td><td>Y</td><td>java.lang.Double.TYPE</td></tr> |
| <tr><td>float</td><td>Y</td><td>java.lang.Float.TYPE</td></tr> |
| <tr><td>big-decimal</td><td>N</td><td>java.math.BigDecimal</td></tr> |
| <tr><td>byte</td><td>Y</td><td>java.lang.Byte.TYPE</td></tr> |
| <tr><td>date</td><td>N</td><td>java.util.Date</td></tr> |
| <tr><td>short</td><td>Y</td><td>java.lang.Short.TYPE</td></tr> |
| <tr><td>char</td><td>Y</td><td>java.lang.Character.TYPE</td></tr> |
| <tr><td>bytes</td><td>N</td><td>byte[]</td></tr> |
| <tr><td>chars</td><td>N</td><td>char[]</td></tr> |
| <tr><td>strings</td><td>N</td><td>String[]</td></tr> |
| <tr><td>locale</td><td>N</td><td>java.util.Locale</td></tr> |
| </table> |
| |
| <p>the CMP Container will try to cast the data in the mapping file to the proper Java |
| type.</p></li> |
| |
| |
| <li><p><b>If there is a collection attribute</b>, the items in the following table can be |
| used:</p> |
| |
| <table border="1" cellpadding="4"> |
| <tr><th>name</th><th>type</th><th>default implementation</th></tr> |
| <tr><td>array</td><td><type_attribute>[]</td><td><type_attribute>[]</td></tr> |
| <tr><td>vector</td><td>java.util.Vector</td><td>java.util.Vector</td></tr> |
| <tr><td>hashtable</td><td>java.util.Hashtable</td><td>java.util.Hashtable</td></tr> |
| <tr><td>collection</td><td>java.util.Collection</td><td>java.util.Arraylist </td></tr> |
| <tr><td>arraylist</td><td>java.util.ArrayList</td><td>java.util.Arraylist </td></tr> |
| <tr><td>set</td><td>java.util.Set</td><td>java.util.Hashset</td></tr> |
| <tr><td>map</td><td>java.util.Map</td><td>java.util.Hashmap</td></tr> |
| </table> |
| |
| <p>The type of the object inside the collection is the 'type' attribute. The 'default |
| implementation' is the type used if the object holding the collection is found |
| to be null and needs to be instantiated.</p> |
| |
| <p>For hashtable and map, the CMP Container will add an object using the put(object, object) |
| method - the object is both the key and the value. This will be improved in the future.</p></li> |
| </ul> |
| |
| <p>It is necessary to use a collection when the content model of the element expects more |
| than one element of the specified type. This is how the 'to-many' portion of a relationship |
| is described.</p> |
| |
| |
| <p><b>2. Determine the signature of the method</b></p> |
| |
| <li><p><b>If 'direct' is set to true</b>, the CMP Container expects to find a public EntityBean or dependent Java |
| object variable with the given signature:</p> |
| |
| <code> |
| public <type> <name>; |
| </code> |
| |
| <li><p><b>If 'direct' is set to false or omitted</b>, the CMP Container will access the property |
| though accessor methods. the CMP Container determines the signature of the accessors and mutators |
| as follows: If the 'get-method' or 'set-method' attributes are supplied, it will |
| try to find a function with the following signature:</p> |
| |
| <code> |
| public <type> <get-method>(); |
| </code> |
| or |
| <code> |
| public void <set-method>(<type> value); |
| </code> |
| |
| <p>If 'get-method' or 'set-method' attributes are not provided, the CMP Container will try to |
| find the following function:</p> |
| |
| <code> |
| public <type> get<capitalized-name>(); |
| </code> |
| or |
| <code> |
| public void set<capitalized-name>(<type> value); |
| </code> |
| |
| <p><capitalized-name> means that the CMP Container uses the <name> attribute by changing its first |
| letter to uppercase without modifying the other letters.</p> |
| |
| <p>The content of the <field> element will contain the information about how to map |
| this field to the relational table.</p> |
| </li> |
| </li> |
| |
| <p>Description of the attributes: </p> |
| |
| <ul> |
| <li><b>name:</b> If 'direct' access is used, 'name' should be the name of a public |
| variable in the object we are mapping (the field must be public, not |
| static and not transient). If no direct access and no 'get-/set-method' |
| is specified, this name will be used to infer the name of the accessor and |
| mutator methods.</li> |
| |
| <li><b>type:</b> The Java type of the field. This is used to access the |
| field. The CMP Container will use this information to cast the data type(e.g. string |
| into integer). It is also used to define the signature of the accessor and |
| mutator methods. If a collection is specified, this is used to specify the |
| type of the object inside the collection. See description above for more |
| details.</li> |
| |
| <li><b>required:</b> If true, the field is not optional.</li> |
| |
| <!-- |
| <li><b>transient:</b> If true, this field will be ignored during the |
| marshalling. This is usefull in when used with the auto-complete |
| option.</li> |
| --> |
| |
| <li><b>direct:</b> If true, the CMP Container expects a public variable in the object |
| and will modify it directly.</li> |
| |
| <li><b>collection:</b> If a parent object expects more than one occurrence of |
| one of its fields, it is necessary to specify which collection type the CMP Container will |
| use to handle them. The type specified is used to define the type of the |
| content inside the collection.</li> |
| |
| <li><b>get-method:</b> An optional name of the accessor method the CMP Container should |
| use. If this attribute is not set, the CMP Container will try to guess the name with the |
| algorithm described above.</li> |
| |
| |
| <li><b>set-method:</b> An optional name of the mutator method the CMP Container should |
| use. If this attribute is not set, the CMP Container will try to guess the name with the |
| algorithm described above.</li> |
| |
| <li><b>create-method:</b> Factory method for instantiation of the object.</li> |
| </ul> |
| |
| </section> |
| |
| <section title="The <sql> element"> |
| |
| <p> |
| <code> |
| <!ELEMENT sql EMPTY> |
| <!ATTLIST sql |
| name NMTOKENS #IMPLIED |
| type NMTOKENS #IMPLIED |
| many-key NMTOKENS #IMPLIED |
| many-table NMTOKEN #IMPLIED |
| read-only ( true | false ) "false" |
| dirty ( check | ignore ) "check"> |
| |
| </code> |
| </p> |
| |
| <p> |
| The <sql> element is used to denote information about the relational |
| database table to which a EntityBean and dependent Java object is mapped. |
| It should be declared |
| for all <field> elements. Each <field> element contains one <sql> |
| element. The <sql> element pertains directly to the the <map-to> |
| element for the containing <class> element. The <sql> elements |
| contains the following attributes: |
| |
| <ul> |
| <li><b>name:</b> The column name in the relational database table.</li> |
| |
| <li><b>type:</b> The column type in the relational database table.</li> |
| |
| <li><b>many-key:</b> Specifies the name of the column that holds the |
| foreign key of the containing object. Used _only_ for 'to-many' relations.</li> |
| |
| <li><b>many-table:</b> Specifies the name of the bridge table that contains |
| the primary keys of the object on each side of the relationship.</li> |
| |
| <li><b>read-only:</b> If true, the column in the relational database |
| table will only be read, not updated or deleted.</li> |
| |
| <li><b>dirty:</b> If the value is 'ignore', the field will not be checked |
| against the database for modification.</li> |
| </ul> |
| </p> |
| |
| </section> |
| |
| </section> |
| |
| |
| <section title="Usage Pattern"> |
| |
| <p>Here is an example of a mapping file and the corresponding EntityBean and dependent Java object and |
| DDL for the databse table.</p> |
| |
| <p>The following is an example Java object:</p> |
| |
| <table border="1" cellpadding="4"> |
| <tr> |
| <td BGCOLOR="#CCCCCC"> |
| <code> |
| package myapp; |
| |
| public class Product implements javax.ejb.EntityBean |
| { |
| private int _id; |
| |
| private String _name; |
| |
| private float _price; |
| |
| private ProductGroup _group; |
| |
| |
| public int getId() |
| ... |
| |
| public void setId( int anId ) |
| ... |
| |
| public String getName() |
| ... |
| |
| public void setName( String aName ) |
| ... |
| |
| public float getPrice() |
| ... |
| |
| public void setPrice( float aPrice ) |
| ... |
| |
| public ProductGroup getProductGroup() |
| ... |
| |
| public void setProductGroup( ProductGroup aProductGroup ) |
| ... |
| } |
| </code> |
| </td> |
| </tr> |
| </table> |
| |
| <p>The following is the relational database table:</p> |
| |
| <table border="1" cellpadding="4"> |
| <tr> |
| <td BGCOLOR="#CCCCCC"> |
| <code> |
| create table prod |
| ( |
| id int not null, |
| name varchar(200) not null, |
| price numeric(18,2) not null, |
| group_id int not null |
| ); |
| </code> |
| </td> |
| </tr> |
| </table> |
| |
| <p>The following is the mapping file for the example EntityBean:</p> |
| |
| <table border="1" cellpadding="4"> |
| <tr> |
| <td BGCOLOR="#CCCCCC"> |
| <code> |
| <?xml version="1.0"?> |
| <!DOCTYPE mapping PUBLIC "-//EXOLAB/Castor Object Mapping DTD Version 1.0//EN" |
| "http://castor.exolab.org/mapping.dtd"> |
| <mapping> |
| |
| <class name="myapp.Product" identity="id"> |
| |
| <map-to table="prod" /> |
| |
| <field name="id" type="integer"> |
| <sql name="id" type="integer" /> |
| </field> |
| |
| <field name="name" type="string"> |
| <sql name="name" type="char" /> |
| </field> |
| |
| <field name="price" type="float"> |
| <sql name="price" type="numeric" /> |
| </field> |
| |
| <field name="group" type="myapp.ProductGroup" > |
| <sql name="group_id" /> |
| </field> |
| |
| </class> |
| |
| </mapping> |
| |
| </code> |
| </td> |
| </tr> |
| </table> |
| |
| </section> |
| |
| </body> |
| </document> |