EJB-JAR.xml file.
<ejb-jar id="ejb-jar_ID">
<enterprise-beans>
<entity id="ContainerManagedEntity_1">
<ejb-name>PersonEJB</ejb-name>
<home>com.ibm.demo.ejbs.PersonHome</home>
<remote>com.ibm.demo.ejbs.Person</remote>
<ejb-class>com.ibm.demo.ejbs.PersonBean</ejb-class>
<persistence-type>Container</persistence-type>
<prim-key-class>java.lang.Integer</prim-key-class>
<reentrant>False</reentrant>
<cmp-field id="CMPAttribute_1">
<field-name>id</field-name>
</cmp-field>
<cmp-field id="CMPAttribute_2">
<field-name>name</field-name>
</cmp-field>
<cmp-field id="CMPAttribute_3">
<field-name>age</field-name>
</cmp-field>
<cmp-field id="CMPAttribute_4">
<field-name>educationLevel</field-name>
</cmp-field>
<primkey-field>id</primkey-field>
</entity>
</enterprise-beans>
...
</ejb-jar>
Table.ddl file, which contains the SQL to create the table for the top-down mapping:
CREATE TABLE PERSONEJB
(ID INTEGER NOT NULL,
NAME VARCHAR(250),
AGE INTEGER,
EDUCATIONLEVEL INTEGER);
ALTER TABLE PERSONEJB
ADD CONSTRAINT PERSONEJBPK PRIMARY KEY (ID);
<ejb-name> tag in the deployment descriptor, and that the columns of the table match the names
in the <cmp-field> tags above.
<primkey-field> tag has been declared NOT NULL
(since it will be the key for this table), and a primary key constraint has been added for this column as well.
Table.ddl
file and understand how WebSphere derived it from the code of your CMP EJB and
the metadata in the EJB deployment descriptor, the next file to investigate
is the schema.dbxmi file held in the Schema
subdirectory of the META-INF directory:
<xmi:XMI xmi:version="2.0" xmlns:xmi="http://www.omg.org/XMI" xmlns:RDBSchema="RDBSchema.xmi">
<RDBSchema:RDBDatabase xmi:id="RDBDatabase_1" name="TopDownDB" tableGroup="RDBTable_1">
<dataTypeSet href="UDBV7_Primitives.xmi#SQLPrimitives_1"/>
</RDBSchema:RDBDatabase>
<RDBSchema:RDBTable xmi:id="RDBTable_1" name="PERSONEJB"
primaryKey="SQLReference_1" database="RDBDatabase_1">
<columns xmi:id="RDBColumn_1" name="ID" allowNull="false"
group="SQLReference_1">
<type xmi:type="RDBSchema:SQLExactNumeric"
xmi:id="SQLExactNumeric_1">
<originatingType xmi:type="RDBSchema:SQLExactNumeric"
href="UDBV7_Primitives.xmi#SQLExactNumeric_1"/>
</type>
</columns>
<columns xmi:id="RDBColumn_2" name="NAME">
<type xmi:type="RDBSchema:SQLCharacterStringType"
xmi:id="SQLCharacterStringType_1" length="250">
<originatingType xmi:type="RDBSchema:SQLCharacterStringType"
href="JavatoDB2UDBNT_V71TypeMaps.xmi#SQLCharacterStringType_250"/>
</type>
</columns>
<columns xmi:id="RDBColumn_3" name="AGE">
<type xmi:type="RDBSchema:SQLExactNumeric"
xmi:id="SQLExactNumeric_2">
<originatingType xmi:type="RDBSchema:SQLExactNumeric"
href="UDBV7_Primitives.xmi#SQLExactNumeric_1"/>
</type>
</columns>
<columns xmi:id="RDBColumn_4" name="EDUCATIONLEVEL">
<type xmi:type="RDBSchema:SQLExactNumeric"
xmi:id="SQLExactNumeric_3">
<originatingType xmi:type="RDBSchema:SQLExactNumeric"
href="UDBV7_Primitives.xmi#SQLExactNumeric_1"/>
</type>
</columns>
<namedGroup xmi:type="RDBSchema:SQLReference"
xmi:id="SQLReference_1"
name="PERSONEJBPK" members="RDBColumn_1" table="RDBTable_1"
constraint="Constraint_PERSONEJBPK"/>
<constraints xmi:id="Constraint_PERSONEJBPK" name="PERSONEJBPK"
type="PRIMARYKEY" primaryKey="SQLReference_1"/>
</RDBSchema:RDBTable>
</xmi:XMI>
<RDBSchema:RDBDatabase xmi:id="RDBDatabase_1" name="TopDownDB" tableGroup="RDBTable_1">
<dataTypeSet href="UDBV7_Primitives.xmi#SQLPrimitives_1"/>
</RDBSchema:RDBDatabase>
<RDBSchema:RDBtable> tag that corresponds to the table defined in the CREATE TABLE SQL above. There
are <columns> tags for each of the columns defined in the table as well. Finally, each <column>
tag contains type information that describes both the originating type and the type of the column.
Here we have an XML definition of the table. At first glance, this doesn't
seem useful, since it is very similar to the information in the Table.ddl file.
However, the next file, the map.mapxmi file, brings everything together and
helps all this make sense:
<ejbrdbmapping:EjbRdbDocumentRoot xmi:version="2.0" xmlns:xmi="http://www.omg.org/XMI"
xmlns:ejbrdbmapping="ejbrdbmapping.xmi" xmlns:ejb="ejb.xmi"
xmlns:RDBSchema="RDBSchema.xmi" xmlns:Mapping="Mapping.xmi"
xmi:id="EjbRdbDocumentRoot_1" outputReadOnly="false" topToBottom="true">
<helper xmi:type="ejbrdbmapping:RdbSchemaProperies"
xmi:id="RdbSchemaProperies_1" primitivesDocument="DB2UDBNT_V71">
<vendorConfiguration
href="RdbVendorConfigurations.xmi#DB2UDBNT_V71_Config"/>
</helper>
<inputs xmi:type="ejb:EJBJar" href="META-INF/ejb-jar.xml#ejb-jar_ID"/>
<outputs xmi:type="RDBSchema:RDBDatabase"
href="META-INF/Schema/Schema.dbxmi#RDBDatabase_1"/>
<nested xmi:type="ejbrdbmapping:RDBEjbMapper" xmi:id="RDBEjbMapper_1">
<helper xmi:type="ejbrdbmapping:PrimaryTableStrategy"
xmi:id="PrimaryTableStrategy_1">
<table href="META-INF/Schema/Schema.dbxmi#RDBTable_1"/>
</helper>
<inputs xmi:type="ejb:ContainerManagedEntity"
href="META-INF/ejb-jar.xml#ContainerManagedEntity_1"/>
<outputs xmi:type="RDBSchema:RDBTable"
href="META-INF/Schema/Schema.dbxmi#RDBTable_1"/>
<nested xmi:id="PersonEJB_id---PERSONEJB_ID">
<inputs xmi:type="ejb:CMPAttribute"
href="META-INF/ejb-jar.xml#CMPAttribute_1"/>
<outputs xmi:type="RDBSchema:RDBColumn"
href="META-INF/Schema/Schema.dbxmi#RDBColumn_1"/>
<typeMapping
href="JavatoDB2UDBNT_V71TypeMaps.xmi#Integer-INTEGER"/>
</nested>
<nested xmi:id="PersonEJB_name---PERSONEJB_NAME">
<inputs xmi:type="ejb:CMPAttribute"
href="META-INF/ejb-jar.xml#CMPAttribute_2"/>
<outputs xmi:type="RDBSchema:RDBColumn"
href="META-INF/Schema/Schema.dbxmi#RDBColumn_2"/>
<typeMapping
href="JavatoDB2UDBNT_V71TypeMaps.xmi#String-VARCHAR"/>
</nested>
<nested xmi:id="PersonEJB_age---PERSONEJB_AGE">
<inputs xmi:type="ejb:CMPAttribute"
href="META-INF/ejb-jar.xml#CMPAttribute_3"/>
<outputs xmi:type="RDBSchema:RDBColumn"
href="META-INF/Schema/Schema.dbxmi#RDBColumn_3"/>
<typeMapping
href="JavatoDB2UDBNT_V71TypeMaps.xmi#int-INTEGER"/>
</nested>
<nested xmi:id="PersonEJB_educationLevel---PERSONEJB_EDUCATIONLEVEL">
<inputs xmi:type="ejb:CMPAttribute"
href="META-INF/ejb-jar.xml#CMPAttribute_4"/>
<outputs xmi:type="RDBSchema:RDBColumn"
href="META-INF/Schema/Schema.dbxmi#RDBColumn_4"/>
<typeMapping
href="JavatoDB2UDBNT_V71TypeMaps.xmi#int-INTEGER"/>
</nested>
</nested>
<typeMapping xmi:type="Mapping:MappingRoot"
href="JavatoDB2UDBNT_V71TypeMaps.xmi#Java_to_DB2UDBNT_V71_TypeMaps"/>
</ejbrdbmapping:EjbRdbDocumentRoot>
Let's start several lines down in this file:
<inputs xmi:type="ejb:ContainerManagedEntity" href="META-INF/ejb-jar.xml#ContainerManagedEntity_1"/>
<outputs xmi:type="RDBSchema:RDBTable" href="META-INF/Schema/Schema.dbxmi#RDBTable_1"/>
ejb-jar.xml file (ContainerManagedEntity_1,
which was the id of the "PersonEJB" we saw earlier),
with a particular database table defined in the schema (RDBTable_1, which is
the PERSONEJB table previously seen in the schema file). In fact, if this were
a multiple-table mapping (one where some columns came from two or more tables),
you'd see multiple <outputs> tags, each
referring to a different schema file and table within that file.
ejb-jar.xml file (CMPAttribute_1, which
is the field id) and a particular database column defined in the schema (RDBColumn_1,
which is the ID column). After the input and output mappings are defined, the
final piece to this puzzle is the type mapping -- which (as you can see) maps
a Java type (Integer) to a relational database type (INTEGER). This kind of
mapping is repeated for all of the CMP fields in the EJB.If you're familiar with Converters in VisualAge® for Java
EJB Support, you'll be relieved to know that the <typeMapping>
tag is used to pick the default converter. If you need a different conversion
than what is specified (say a specialized converter that knows how to convert
the special Strings "Yes" and "No" to a boolean), you can specify this through
a <helper> tag at this point.
Figure 2 below shows the interaction between these three primary XML files and their constituent parts.
Simple Metadata Tricks
<RDBSchema:RDBDatabase xmi:id="RDBDatabase_1" name="DEV" tableGroup="RDBTable_1">
Another simple change you can make is to update the XML to
perform a minimal meet-in-the-middle mapping when either the EJB definition
or the database schema changes. For instance, suppose you decide later in the
project to change the name of the educationLevel CMP field to edLevel. You'd
only need to update the ejb-jar.xml file to
change the field like this:
<field-name>edLevel>/field-name>
</cmp-field>
ejb-jar.xml the same, while updating the
schema.dbxmi file appropriately. Again, in either case, redeploy the EJB jar file after editing the XML.