Using CMP2.0 persistence

This document highlights the main differences between CMP as defined in EJB 2.0 specification (called CMP2.0) and CMP as defined in EJB 1.1 specification (called CMP1.1). Major new features in the standard development and deployment of CMP2.0 entity beans are listed (comparing them to CMP1.1), along with JOnAS-specific information. Mapping CMP2.0 entity beans to the database is described in detail. Note that the database mapping can be created entirely by JOnAS, in which case the JOnAS-specific deployment descriptor for an entity bean should contain only the datasource and the element indicating how the database should be initialized.

The content of this guide is the following:

  1. Standard CMP2.0 Aspects
    1. Entity Bean Implementation Class
    2. Standard Deployment Descriptor
  2. JOnAS Database Mappers
  3. JOnAS Database Mapping (Specific Deployment Descriptor)
    1. Specifying and Initializing the Database
    2. CMP fields Mapping
    3. CMR fields Mapping to primary-key-fields (simple pk)
      1. 1-1 unidirectional relationships
      2. 1-1 bidirectional relationships
      3. 1-N unidirectional relationships
      4. 1-N bidirectional relationships
      5. N-1 unidirectional relationships
      6. N-M unidirectional relationships
      7. N-M bidirectional relationships
    4. CMR fields Mapping to composite primary-keys
      1. 1-1 bidirectional relationship
      2. N-M unidirectional relationship

Standard CMP2.0 Aspects

This section briefly describes the new features available in CMP2.0 as compared to CMP 1.1, and how these features change the development of entity beans.

Entity Bean Implementation Class

The EJB implementation class 1) implements the bean's business methods of the component interface, 2) implements the methods dedicated to the EJB environment (the interface of which is explicitly defined in the EJB specification), and 3) defines the abstract methods representing both the persistent fields (cmp-fields) and the relationship fields (cmr-fields). The class must implement the javax.ejb.EntityBean interface, be defined as public, and be abstract (which is not the case for CMP1.1, where it must not be abstract). The abstract methods are the get and set accessor methods of the bean cmp and cmr fields. Refer to the examples and details in the section "Developing Entity Beans" of the JOnAS documentation.

Standard Deployment Descriptor

The standard way to indicate to an EJB platform that an entity bean has container-managed persistence is to fill the <persistence-type> tag of the deployment descriptor with the value "container," and to fill the <cmp-field> tags of the deployment descriptor with the list of container-managed fields (the fields that the container will have in charge to make persistent) and the <cmr-field> tags identifying the relationships. The CMP version (1.x or 2.x) should also be specified in the <cmp-version> tag. This is represented by the following lines in the deployment descriptor:

    <persistence-type>container</persistence-type>
    <cmp-version>1.x</cmp-version>
    <cmp-field>
      <field-name>fieldOne</field-name>
    </cmp-field>
    <cmp-field>
      <field-name>fieldTwo</field-name>
    </cmp-field>
    

Note that for running CMP1.1-defined entity beans on an EJB2.0 platform, such as JOnAS 3.x, you must introduce this <cmp-version> element in your deployment descriptors, since the default cmp-version value (if not specified) is 2.x.

Note that for CMP 2.0, the information defining the behaviour of the implementation of a find<method> method is located in the standard deployment descriptor as an EJB-QL query (this is not JOnAS-specific information). For CMP 1.1, this information is located in the JOnAS-specific deployment descriptor as an SQL WHERE clause specified in a <finder-method-jdbc-mapping> element.

Finder method example in CMP 2.0: for a findLargeAccounts(double val) method defined on the Account entity bean of the JOnAS eb example.

      <query>
        <query-method>
          <method-name>findLargeAccounts</method-name>
          <method-params>
              <method-param>double</method-param>
          </method-params>
        </query-method>
        <ejb-ql>SELECT OBJECT(o) FROM accountsample o WHERE o.balance &gt; ?1</ejb-ql>
      </query>
    

JOnAS Database mappers

For implementing the EJB 2.0 persistence (CMP2.0), JOnAS relies on the JORM framework. JORM itself relies on JOnAS DataSources (specified in DataSource properties files) for connecting to the actual database. JORM must adapt its object-relational mapping to the underlying database, for which it makes use of adapters called "mappers." Thus, for each type of database (and more precisely for each JDBC driver), the corresponding mapper must be specified in the DataSource. This is the purpose of the datasource.mapper property of the DataSource properties file. Note that all JOnAS-provided DataSource properties files (in JOnAS_ROOT/conf) already contain this property with the correct mapper.

property name description possible values
datasource.mapper JORM database mapper
  • rdb: generic mapper (JDBC standard driver ...)
  • rdb.firebird: Firebird
  • rdb.mckoi: McKoi Db
  • rdb.mysql: MySQL
  • rdb.oracle8: Oracle 8 and lesser versions
  • rdb.oracle: Oracle 9
  • rdb.postgres: PostgreSQL (>= 7.2)
  • rdb.sapdb: Sap DB
  • rdb.sqlserver: MS Sql Server
  • rdb.sybase: Sybase

Contact the JOnAS team to obtain a mapper for other databases.

The container code generated at deployment (GenIC or ejbjar ant task) is dependent on this mapper. It is possible to deploy (generate container code) a bean for several mappers in order to change the database (i.e. the DataSource file) without redeploying the bean. These mappers should be specified as the mappernames argument of the GenIC command or as the mappernames attribute of the JOnAS ANT ejbjar task. The value is a comma-separated list of mapper names for which the container classes will be generated. This list of mapper names corresponds to the list of potential databases upon which you can deploy your entity beans. For example, to deploy entity beans so that they may be used on either Oracle or PostgreSQL, run GenIC as:

         GenIC -mappernames rdb.oracle,rdb.postgres eb.jar
    

The following is the same example in an ANT build.xml file:

  <target name="deploy"
          description="Build and deploy the ejb-jars"
          depends="compile>
    <ejbjar naming="directory"
        ....
        ....
      <jonas destdir="${ejbjars.dir}"
             jonasroot="${jonas.root}"
             orb="${orb}"
             jarsuffix=".jar"
             secpropag="yes"
             keepgenerated="true"
             mappernames="${mapper.names}"
             additionalargs="${genicargs}">
      </jonas>
      ...
      ... 
    </ejbjar>
  </target>
    

having in build.properties:

# mappers for entity CMP2
mapper.names            rdb.oracle,rdb.postgres
    

JOnAS Database Mapping (Specific Deployment Descriptor)

The mapping to the database of entity beans and their relationships may be specified in the JOnAS-specific deployment descriptor, in jonas-entity elements, and in jonas-ejb-relation elements. Since JOnAS is able to generate the database mapping, all the elements of the JOnAS-specific deployment descriptor defined in this section (which are sub-elements of jonas-entity or jonas-ejb-relation) are optional, except those for specifying the datasource and the initialization mode (i.e. the jndi-name of jdbc-mapping and cleanup). The default values of these mapping elements, provided in this section, define the JOnAS-generated database mapping.

Specifying and Initializing the Database

For specifying the database within which a CMP 2.0 entity bean is stored, the jndi-name element of the jdbc-mapping is necessary. This is the JNDI name of the DataSource representing the database storing the entity bean.

    <jdbc-mapping>
      <jndi-name>jdbc_1</jndi-name>
    </jdbc-mapping>
    

For a CMP 2.0 entity bean, the JOnAS-specific deployment descriptor contains an additional element, cleanup, to be specified before the jdbc-mapping element, which can have one of the following values:

removedata
at bean loading time, the content of the tables storing the bean data is deleted
removeall
at bean loading time, the tables storing the bean data are dropped (if they exist) and created
none
do nothing
create
default value (if the element is not specified), at bean loading time, the tables for storing the bean data are created if they do not exist.

It may be useful for testing purposes to delete the database data each time a bean is loaded. For this purpose, the part of the JOnAS-specific deployment descriptor related to the entity bean may look like the following:

    <cleanup>removedata</cleanup>
    <jdbc-mapping>
      <jndi-name>jdbc_1</jndi-name>
    </jdbc-mapping>
    

CMP fields Mapping

Mapping CMP fields in CMP2.0 is similar to that of CMP 1.1, but in CMP2.0 it is also possible to specify the SQL type of a column. Usually this SQL type is used if JOnAS creates the table (create value of the cleanup element), and if the JORM default chosen SQL type is not appropriate.

Standard Deployment Descriptor
    .....
    <entity>
      <ejb-name>A</ejb-name>
      .....
      <cmp-field>
        <field-name>idA</field-name>
      </cmp-field>
      <cmp-field>
        <field-name>f</field-name>
      </cmp-field>
    .....
    </entity>
    .....
    
Database Mapping
t_A
c_idA c_f
... ...
JOnAS Deployment Descriptor
    .....
    <jonas-entity>
      <ejb-name>A</ejb-name>
      .....
      <jdbc-mapping>
        <jndi-name>jdbc_1</jndi-name>
        <jdbc-table-name>t_A</jdbc-table-name>
        <cmp-field-jdbc-mapping>
          <field-name>idA</field-name>
          <jdbc-field-name>c_idA</jdbc-field-name>
        </cmp-field-jdbc-mapping>
        <cmp-field-jdbc-mapping>
          <field-name>f</field-name>
          <jdbc-field-name>c_f</jdbc-field-name>
          <sql-type>varchar(40)</sql-type>
        </cmp-field-jdbc-mapping>
      </jdbc-mapping>
      .....
    </jonas-entity>
    .....
    

Defaults values:

jndi-name Mandatory
jdbc-table-name Optional.
Default value is the upper-case CMP2 abstract-schema-name, or the CMP1 ejb-name, suffixed by _.
cmp-field-jdbc-mapping Optional.
jdbc-field-name Optional.
Default value is the field-name suffixed by _.
idA_ and f_ in the example.
sql-type Optional.
Default value defined by JORM.
 

CMR fields Mapping to primary-key-fields (simple pk)

1-1 unidirectional relationships

Standard Deployment Descriptor
    .....
    <entity>
      <ejb-name>A</ejb-name>
      .....
      <cmp-field>
        <field-name>idA</field-name>
      </cmp-field>
      <primkey-field>idA</primkey-field>
      .....
    </entity>
    .....
    <entity>
      <ejb-name>B</ejb-name>
      .....
      <cmp-field>
        <field-name>idB</field-name>
      </cmp-field>
      <primkey-field>idB</primkey-field>
      .....
    </entity>
    .....
    <relationships>
      <ejb-relation>
        <ejb-relation-name>a-b</ejb-relation-name>
        <ejb-relationship-role>
          <!-- A => B -->
                <ejb-relationship-role-name>a2b</ejb-relationship-role-name>
          <multiplicity>One</multiplicity>
          <relationship-role-source>
            <ejb-name>A</ejb-name>
          </relationship-role-source>
          <cmr-field>
            <cmr-field-name>b</cmr-field-name>
          </cmr-field>
        </ejb-relationship-role>
        <ejb-relationship-role>
          <!-- B => A -->
          <ejb-relationship-role-name>b2a</ejb-relationship-role-name>
          <multiplicity>One</multiplicity>
          <relationship-role-source>
            <ejb-name>B</ejb-name>
          </relationship-role-source>
        </ejb-relationship-role>
      </ejb-relation>
    </relationships>
    .....
    
Database Mapping
t_A
c_idA cfk_idB
... ...
t_B
c_idB
...

There is a foreign key in the table of the bean that owns the CMR field.

JOnAS Deployment Descriptor
    .....
    <jonas-entity>
      <ejb-name>A</ejb-name>
      .....
      <jdbc-mapping>
        <jndi-name>jdbc_1</jndi-name>
        <jdbc-table-name>t_A/jdbc-table-name>
        <cmp-field-jdbc-mapping>
          <field-name>idA</field-name>
          <jdbc-field-name>c_idA</jdbc-field-name>
        </cmp-field-jdbc-mapping>
      </jdbc-mapping>
      .....
    </jonas-entity>
    .....
    <jonas-entity>
      <ejb-name>B</ejb-name>
      .....
      <jdbc-mapping>
        <jndi-name>jdbc_1</jndi-name>
        <jdbc-table-name>t_B/jdbc-table-name>
        <cmp-field-jdbc-mapping>
          <field-name>idB</field-name>
          <jdbc-field-name>c_idB</jdbc-field-name>
        </cmp-field-jdbc-mapping>
      </jdbc-mapping>
      .....
    </jonas-entity>
    .....
    <jonas-ejb-relation>
      <ejb-relation-name>a-b</ejb-relation-name>
      <jonas-ejb-relationship-role>
        <ejb-relationship-role-name>a2b</ejb-relationship-role-name>
        <foreign-key-jdbc-mapping>
          <foreign-key-jdbc-name>cfk_idb</foreign-key-jdbc-name>
        </foreign-key-jdbc-mapping>
      </jonas-ejb-relationship-role>
    </jonas-ejb-relation>
    .....
    

foreign-key-jdbc-name is the column name of the foreign key in the table of the source bean of the relationship-role.
In this example, where the destination bean has a primary-key-field, it is possible to deduce that this foreign-key-jdbc-name column is to be associated with the column of this primary-key-field in the table of the destination bean.

Default values:

jonas-ejb-relation Optional
foreign-key-jdbc-name Optional.
Default value is the abstract-schema-name of the destination bean, suffixed by _, and by its primary-key-field.
B_idb in the example.
 

1-1 bidirectional relationships

Compared to 1-1 unidirectional relationships, there is a CMR field in both of the beans, thus making two types of mapping possible.

Standard Deployment Descriptor
    .....
    <relationships>
      <ejb-relation>
        <ejb-relation-name>a-b</ejb-relation-name>
        <ejb-relationship-role>
          <!-- A => B -->
                <ejb-relationship-role-name>a2b</ejb-relationship-role-name>
          <multiplicity>One</multiplicity>
          <relationship-role-source>
            <ejb-name>A</ejb-name>
          </relationship-role-source>
          <cmr-field>
            <cmr-field-name>b</cmr-field-name>
          </cmr-field>
        </ejb-relationship-role>
        <ejb-relationship-role>
          <!-- B => A -->
          <ejb-relationship-role-name>b2a</ejb-relationship-role-name>
          <multiplicity>One</multiplicity>
          <relationship-role-source>
            <ejb-name>B</ejb-name>
          </relationship-role-source>
          <cmr-field>
            <cmr-field-name>a</cmr-field-name>
          </cmr-field>
        </ejb-relationship-role>
      </ejb-relation>
    </relationships>
    .....
    
Database Mapping

Two mappings are possible. One of the tables may hold a foreign key.

Case 1:

t_A
c_idA cfk_idB
... ...
t_B
c_idB
...

Case 2:

t_A
c_idA
...
t_B
c_idB cfk_idA
... ...
JOnAS Deployment Descriptor

Case 1:

    .....
    <jonas-ejb-relation>
      <ejb-relation-name>a-b</ejb-relation-name>
      <jonas-ejb-relationship-role>
        <ejb-relationship-role-name>a2b</ejb-relationship-role-name>
        <foreign-key-jdbc-mapping>
          <foreign-key-jdbc-name>cfk_idb</foreign-key-jdbc-name>
        </foreign-key-jdbc-mapping>
      </jonas-ejb-relationship-role>
    </jonas-ejb-relation>
    .....
    

Case 2:

    .....
    <jonas-ejb-relation>
      <ejb-relation-name>a-b</ejb-relation-name>
      <jonas-ejb-relationship-role>
        <ejb-relationship-role-name>b2a</ejb-relationship-role-name>
        <foreign-key-jdbc-mapping>
          <foreign-key-jdbc-name>cfk_ida</foreign-key-jdbc-name>
        </foreign-key-jdbc-mapping>
      </jonas-ejb-relationship-role>
    </jonas-ejb-relation>
    .....
    

For the default mapping, the foreign key is in the table of the source bean of the first ejb-relationship-role of the ejb-relation. In the example, the default mapping corresponds to case 1, since the ejb-relationship-role a2b is the first defined in the ejb-relation a-b. Then, the default values are similar to those of the 1-1 unidirectional relationship.

 

1-N unidirectional relationships

Standard Deployment Descriptor
    .....
    <relationships>
      <ejb-relation>
        <ejb-relation-name>a-b</ejb-relation-name>
        <ejb-relationship-role>
          <!-- A => B -->
                <ejb-relationship-role-name>a2b</ejb-relationship-role-name>
          <multiplicity>One</multiplicity>
          <relationship-role-source>
            <ejb-name>A</ejb-name>
          </relationship-role-source>
          <cmr-field>
            <cmr-field-name>b</cmr-field-name>
            <cmr-field-type>java.util.Collection</cmr-field-type>
          </cmr-field>
        </ejb-relationship-role>
        <ejb-relationship-role>
          <!-- B => A -->
          <ejb-relationship-role-name>b2a</ejb-relationship-role-name>
          <multiplicity>Many</multiplicity>
          <relationship-role-source>
            <ejb-name>B</ejb-name>
          </relationship-role-source>
        </ejb-relationship-role>
      </ejb-relation>
    </relationships>
    .....
    
Database Mapping
t_A
c_idA
...
t_B
c_idB cfk_idA
... ...

In this case, the foreign key must be in the table of the bean which is on the "many" side of the relationship (i.e. in the table of the source bean of the relationship role with multiplicity many), t_B.

JOnAS Deployment Descriptor
    .....
    <jonas-ejb-relation>
      <ejb-relation-name>a-b</ejb-relation-name>
      <jonas-ejb-relationship-role>
        <ejb-relationship-role-name>b2a</ejb-relationship-role-name>
        <foreign-key-jdbc-mapping>
          <foreign-key-jdbc-name>cfk_ida</foreign-key-jdbc-name>
        </foreign-key-jdbc-mapping>
      </jonas-ejb-relationship-role>
    </jonas-ejb-relation>
    .....
    

Default values:

jonas-ejb-relation Optional
foreign-key-jdbc-name Optional.
Default value is the abstract-schema-name of the destination bean of the "one" side of the relationship (i.e. the source bean of the relationship role with multiplicity one), suffixed by _, and by its primary-key-field.
A_ida in the example.
 

1-N bidirectional relationships

Similar to 1-N unidirectional relationships, but with a CMR field in each bean.

Standard Deployment Descriptor
    .....
    <relationships>
      <ejb-relation>
        <ejb-relation-name>a-b</ejb-relation-name>
        <ejb-relationship-role>
          <!-- A => B -->
                <ejb-relationship-role-name>a2b</ejb-relationship-role-name>
          <multiplicity>One</multiplicity>
          <relationship-role-source>
            <ejb-name>A</ejb-name>
          </relationship-role-source>
          <cmr-field>
            <cmr-field-name>b</cmr-field-name>
            <cmr-field-type>java.util.Collection</cmr-field-type>
          </cmr-field>
        </ejb-relationship-role>
        <ejb-relationship-role>
          <!-- B => A -->
          <ejb-relationship-role-name>b2a</ejb-relationship-role-name>
          <multiplicity>Many</multiplicity>
          <relationship-role-source>
            <ejb-name>B</ejb-name>
          </relationship-role-source>
          <cmr-field>
            <cmr-field-name>a</cmr-field-name>
          </cmr-field>
        </ejb-relationship-role>
      </ejb-relation>
    </relationships>
    .....
    
Database mapping
t_A
c_idA
...
t_B
c_idB cfk_idA
... ...

In this case, the foreign key must be in the table of the bean which is on the "many" side of the relationship (i.e. in the table of the source bean of the relationship role with multiplicity many), t_B.

JOnAS Deployment Descriptor
    .....
    <jonas-ejb-relation>
      <ejb-relation-name>a-b</ejb-relation-name>
      <jonas-ejb-relationship-role>
        <ejb-relationship-role-name>b2a</ejb-relationship-role-name>
        <foreign-key-jdbc-mapping>
          <foreign-key-jdbc-name>cfk_ida</foreign-key-jdbc-name>
        </foreign-key-jdbc-mapping>
      </jonas-ejb-relationship-role>
    </jonas-ejb-relation>
    .....
    

Default values:

jonas-ejb-relation Optional
foreign-key-jdbc-name Optional.
Default value is the abstract-schema-name of the destination bean of the "one" side of the relationship (i.e. the source bean of the relationship role with multiplicity one), suffixed by _, and by its primary-key-field.
A_ida in the example.
 

N-1 unidirectional relationships

Similar to 1-N unidirectional relationships, but the CMR field is defined on the "many" side of the relationship, i.e. on the (source bean of the) relationship role with multiplicity "many."

Standard Deployment Descriptor
    .....
    <relationships>
      <ejb-relation>
        <ejb-relation-name>a-b</ejb-relation-name>
        <ejb-relationship-role>
          <!-- A => B -->
                <ejb-relationship-role-name>a2b</ejb-relationship-role-name>
          <multiplicity>Many</multiplicity>
          <relationship-role-source>
            <ejb-name>A</ejb-name>
          </relationship-role-source>
          <cmr-field>
            <cmr-field-name>b</cmr-field-name>
          </cmr-field>
        </ejb-relationship-role>
        <ejb-relationship-role>
          <!-- B => A -->
          <ejb-relationship-role-name>b2a</ejb-relationship-role-name>
          <multiplicity>One</multiplicity>
          <relationship-role-source>
            <ejb-name>B</ejb-name>
          </relationship-role-source>
        </ejb-relationship-role>
      </ejb-relation>
    </relationships>
    .....
    
Database mapping
t_A
c_idA cfk_idB
... ...
t_B
c_idB
...

In this case, the foreign key must be in the table of the bean which is on the "many" side of the relationship (i.e. in table of the source bean of the relationship role with multiplicity many), t_A.

JOnAS Deployment Descriptor
    .....
    <jonas-ejb-relation>
      <ejb-relation-name>a-b</ejb-relation-name>
      <jonas-ejb-relationship-role>
        <ejb-relationship-role-name>a2b</ejb-relationship-role-name>
        <foreign-key-jdbc-mapping>
          <foreign-key-jdbc-name>cfk_idb</foreign-key-jdbc-name>
        </foreign-key-jdbc-mapping>
      </jonas-ejb-relationship-role>
    </jonas-ejb-relation>
    .....
    

Default values:

jonas-ejb-relation Optional
foreign-key-jdbc-name Optional.
Default value is the abstract-schema-name of the destination bean of the "one" side of the relationship (i.e. the source bean of the relationship role with multiplicity one), suffixed by _, and by its primary-key-field.
B_idb in the example.
 

N-M unidirectional relationships

Standard Deployment Descriptor
    .....
    <relationships>
      <ejb-relation>
        <ejb-relation-name>a-b</ejb-relation-name>
        <ejb-relationship-role>
          <!-- A => B -->
                <ejb-relationship-role-name>a2b</ejb-relationship-role-name>
          <multiplicity>Many</multiplicity>
          <relationship-role-source>
            <ejb-name>A</ejb-name>
          </relationship-role-source>
          <cmr-field>
            <cmr-field-name>b</cmr-field-name>
            <cmr-field-type>java.util.Collection</cmr-field-type>
          </cmr-field>
        </ejb-relationship-role>
        <ejb-relationship-role>
          <!-- B => A -->
          <ejb-relationship-role-name>b2a</ejb-relationship-role-name>
          <multiplicity>Many</multiplicity>
          <relationship-role-source>
            <ejb-name>B</ejb-name>
          </relationship-role-source>
        </ejb-relationship-role>
      </ejb-relation>
    </relationships>
    .....
    
Database mapping
t_A
c_idA
...
t_B
c_idB
...
tJoin_AB
cfk_idA cfk_idB
... ...

In this case, there is a join table composed of the foreign keys of each entity bean table.

JOnAS Deployment Descriptor
    .....
    <jonas-ejb-relation>
      <ejb-relation-name>a-b</ejb-relation-name>
      <jdbc-table-name>tJoin_AB</jdbc-table-name>
      <jonas-ejb-relationship-role>
        <ejb-relationship-role-name>a2b</ejb-relationship-role-name>
        <foreign-key-jdbc-mapping>
          <foreign-key-jdbc-name>cfk_idb</foreign-key-jdbc-name>
        </foreign-key-jdbc-mapping>
      </jonas-ejb-relationship-role>
      <jonas-ejb-relationship-role>
        <ejb-relationship-role-name>b2a</ejb-relationship-role-name>
        <foreign-key-jdbc-mapping>
          <foreign-key-jdbc-name>cfk_ida</foreign-key-jdbc-name>
        </foreign-key-jdbc-mapping>
      </jonas-ejb-relationship-role>
    </jonas-ejb-relation>
    .....
    

Default values

jonas-ejb-relation Optional
jdbc-table-name Optional.
Default value is built from the abstract-schema-names of the beans, separated by _.
A_B in the example.
foreign-key-jdbc-name Optional.
Default value is the abstract-schema-name of the destination bean, suffixed by _, and by its primary-key-field.
B_idb and A_ida in the example.
 

N-M bidirectional relationships

Similar to N-M unidirectional relationships, but a CMR field is defined for each bean.

Standard deployment Descriptor
    .....
    <relationships>
      <ejb-relation>
        <ejb-relation-name>a-b</ejb-relation-name>
        <ejb-relationship-role>
          <!-- A => B -->
                <ejb-relationship-role-name>a2b</ejb-relationship-role-name>
          <multiplicity>Many</multiplicity>
          <relationship-role-source>
            <ejb-name>A</ejb-name>
          </relationship-role-source>
          <cmr-field>
            <cmr-field-name>b</cmr-field-name>
            <cmr-field-type>java.util.Collection</cmr-field-type>
          </cmr-field>
        </ejb-relationship-role>
        <ejb-relationship-role>
          <!-- B => A -->
          <ejb-relationship-role-name>b2a</ejb-relationship-role-name>
          <multiplicity>Many</multiplicity>
          <relationship-role-source>
            <ejb-name>B</ejb-name>
          </relationship-role-source>
          <cmr-field>
            <cmr-field-name>a</cmr-field-name>
            <cmr-field-type>java.util.Collection</cmr-field-type>
          </cmr-field>
        </ejb-relationship-role>
      </ejb-relation>
    </relationships>
    .....
    
Database mapping
t_A
c_idA
...
t_B
c_idB
...
tJoin_AB
cfk_idA cfk_idB
... ...

In this case, there is a join table composed of the foreign keys of each entity bean table.

JOnAS Deployment Descriptor
    .....
    <jonas-ejb-relation>
      <ejb-relation-name>a-b</ejb-relation-name>
      <jdbc-table-name>tJoin_AB</jdbc-table-name>
      <jonas-ejb-relationship-role>
        <ejb-relationship-role-name>a2b</ejb-relationship-role-name>
        <foreign-key-jdbc-mapping>
          <foreign-key-jdbc-name>cfk_idb</foreign-key-jdbc-name>
        </foreign-key-jdbc-mapping>
      </jonas-ejb-relationship-role>
      <jonas-ejb-relationship-role>
        <ejb-relationship-role-name>b2a</ejb-relationship-role-name>
        <foreign-key-jdbc-mapping>
          <foreign-key-jdbc-name>cfk_ida</foreign-key-jdbc-name>
        </foreign-key-jdbc-mapping>
      </jonas-ejb-relationship-role>
    </jonas-ejb-relation>
    .....
    

Default values:

jonas-ejb-relation Optional
jdbc-table-name Optional.
Default value is built from the abstract-schema-names of the beans, separated by _.
A_B in the example.
foreign-key-jdbc-name Optional.
Default value is the abstract-schema-name of the destination bean, suffixed by _, and by its primary-key-field.
B_idb and A_ida in the example.
 

CMR fields Mapping to composite primary-keys

In the case of composite primary keys, the database mapping should provide the capability to specify which column of a foreign key corresponds to which column of the primary key. This is the only difference between relationships based on simple primary keys. For this reason, not all types of relationship are illustrated below.

1-1 bidirectional relationships

Standard Deployment Descriptor
    .....
    <entity>
      <ejb-name>A</ejb-name>
      .....
      <prim-key-class>p.PkA</prim-key-class>
      .....
      <cmp-field>
        <field-name>id1A</field-name>
      </cmp-field>
      <cmp-field>
        <field-name>id2A</field-name>
      </cmp-field>
      .....
    </entity>
    .....
    <entity>
      <ejb-name>B</ejb-name>
      .....
      <prim-key-class>p.PkB</prim-key-class>
      .....
      <cmp-field>
        <field-name>id1B</field-name>
      </cmp-field>
      <cmp-field>
        <field-name>id2B</field-name>
      </cmp-field>
      .....
    </entity>
    .....
    <relationships>
      <ejb-relation>
        <ejb-relation-name>a-b</ejb-relation-name>
        <ejb-relationship-role>
          <!-- A => B -->
                <ejb-relationship-role-name>a2b</ejb-relationship-role-name>
          <multiplicity>One</multiplicity>
          <relationship-role-source>
            <ejb-name>A</ejb-name>
          </relationship-role-source>
          <cmr-field>
            <cmr-field-name>b</cmr-field-name>
          </cmr-field>
        </ejb-relationship-role>
        <ejb-relationship-role>
          <!-- B => A -->
          <ejb-relationship-role-name>b2a</ejb-relationship-role-name>
          <multiplicity>One</multiplicity>
          <relationship-role-source>
            <ejb-name>B</ejb-name>
          </relationship-role-source>
          <cmr-field>
            <cmr-field-name>a</cmr-field-name>
          </cmr-field>
        </ejb-relationship-role>
      </ejb-relation>
    </relationships>
    .....
    
Database mapping

Two mappings are possible, one or another of the tables may hold the foreign key.

Case 1:

t_A
c_id1A c_id2A cfk_id1B cfk_id2B
... ... ... ...
t_B
c_id1B c_id2B
... ...

Case 2:

t_A
c_id1A c_id2A
... ...
t_B
c_id1B c_id2B cfk_id1A cfk_id2A
... ... ... ...
JOnAS Deployment Descriptor

Case 1:

    .....
    <jonas-ejb-relation>
      <ejb-relation-name>a-b</ejb-relation-name>
      <jonas-ejb-relationship-role>
        <ejb-relationship-role-name>a2b</ejb-relationship-role-name>
        <foreign-key-jdbc-mapping>
          <foreign-key-jdbc-name>cfk_id1b</foreign-key-jdbc-name>
          <key-jdbc-name>c_id1b</key-jdbc-name>
        </foreign-key-jdbc-mapping>
        <foreign-key-jdbc-mapping>
          <foreign-key-jdbc-name>cfk_id2b</foreign-key-jdbc-name>
          <key-jdbc-name>c_id2b</key-jdbc-name>
        </foreign-key-jdbc-mapping>
      </jonas-ejb-relationship-role>
    </jonas-ejb-relation>
    .....
    

Case 2:

    .....
    <jonas-ejb-relation>
      <ejb-relation-name>a-b</ejb-relation-name>
      <jonas-ejb-relationship-role>
        <ejb-relationship-role-name>b2a</ejb-relationship-role-name>
        <foreign-key-jdbc-mapping>
          <foreign-key-jdbc-name>cfk_id1a</foreign-key-jdbc-name>
          <key-jdbc-name>c_id1a</key-jdbc-name>
        </foreign-key-jdbc-mapping>
        <foreign-key-jdbc-mapping>
          <foreign-key-jdbc-name>cfk_id2a</foreign-key-jdbc-name>
          <key-jdbc-name>c_id2a</key-jdbc-name>
        </foreign-key-jdbc-mapping>
      </jonas-ejb-relationship-role>
    </jonas-ejb-relation>
    .....
    

For the default mapping (values), the foreign key is in the table of the source bean of the first ejb-relationship-role of the ejb-relation. In the example, the default mapping corresponds to case 1, since the ejb-relationship-role a2b is the first defined in the ejb-relation a-b.

 

N-M unidirectional relationships

Standard Deployment Descriptor
    .....
    <entity>
      <ejb-name>A</ejb-name>
      .....
      <cmp-field>
        <field-name>id1A</field-name>
      </cmp-field>
      <cmp-field>
        <field-name>id2A</field-name>
      </cmp-field>
      .....
    </entity>
    .....
    <entity>
      <ejb-name>B</ejb-name>
      .....
      <cmp-field>
        <field-name>id1B</field-name>
      </cmp-field>
      <cmp-field>
        <field-name>id2B</field-name>
      </cmp-field>
      .....
    </entity>
    .....
    <relationships>
      <ejb-relation>
        <ejb-relation-name>a-b</ejb-relation-name>
        <ejb-relationship-role>
          <!-- A => B -->
                <ejb-relationship-role-name>a2b</ejb-relationship-role-name>
          <multiplicity>Many</multiplicity>
          <relationship-role-source>
            <ejb-name>A</ejb-name>
          </relationship-role-source>
          <cmr-field>
            <cmr-field-name>b</cmr-field-name>
            <cmr-field-type>java.util.Collection</cmr-field-type>
          </cmr-field>
        </ejb-relationship-role>
        <ejb-relationship-role>
          <!-- B => A -->
          <ejb-relationship-role-name>b2a</ejb-relationship-role-name>
          <multiplicity>Many</multiplicity>
          <relationship-role-source>
            <ejb-name>B</ejb-name>
          </relationship-role-source>
        </ejb-relationship-role>
      </ejb-relation>
    </relationships>
    .....
    
Database mapping
t_A
c_id1A c_id2A
... ...
t_B
c_id1B c_id2B
... ...
tJoin_AB
cfk_id1A cfk_id2A cfk_id1B cfk_id2B
... ... ... ...

In this case, there is a join table composed of the foreign keys of each entity bean table.

JOnAS Deployment Descriptor
    .....
    <jonas-ejb-relation>
      <ejb-relation-name>a-b</ejb-relation-name>
      <jdbc-table-name>tJoin_AB</jdbc-table-name>
      <jonas-ejb-relationship-role>
        <ejb-relationship-role-name>a2b</ejb-relationship-role-name>
        <foreign-key-jdbc-mapping>
          <foreign-key-jdbc-name>cfk_id1b</foreign-key-jdbc-name>
          <key-jdbc-name>c_id1b</key-jdbc-name>
        </foreign-key-jdbc-mapping>
        <foreign-key-jdbc-mapping>
          <foreign-key-jdbc-name>cfk_id2b</foreign-key-jdbc-name>
          <key-jdbc-name>c_id2b</key-jdbc-name>
        </foreign-key-jdbc-mapping>
      </jonas-ejb-relationship-role>
      <jonas-ejb-relationship-role>
        <ejb-relationship-role-name>b2a</ejb-relationship-role-name>
        <foreign-key-jdbc-mapping>
          <foreign-key-jdbc-name>cfk_id1a</foreign-key-jdbc-name>
          <key-jdbc-name>c_id1a</key-jdbc-name>
        </foreign-key-jdbc-mapping>
        <foreign-key-jdbc-mapping>
          <foreign-key-jdbc-name>cfk_id2a</foreign-key-jdbc-name>
          <key-jdbc-name>c_id2a</key-jdbc-name>
        </foreign-key-jdbc-mapping>
      </jonas-ejb-relationship-role>
    </jonas-ejb-relation>
    .....