<?xml version="1.0" encoding="UTF-8"?>
<section version="5.0" 
         xmlns="http://docbook.org/ns/docbook" 
         xmlns:xlink="http://www.w3.org/1999/xlink" 
         xmlns:xi="http://www.w3.org/2001/XInclude" 
         xmlns:svg="http://www.w3.org/2000/svg" 
         xmlns:mml="http://www.w3.org/1998/Math/MathML" 
         xmlns:html="http://www.w3.org/1999/xhtml" 
         xmlns:db="http://docbook.org/ns/docbook" 
         xml:lang="en" 
         xml:id="ejb.config.db.cmp2">

<info><title>Configuring Database Access for Container Managed Persistence</title></info>

  

  <para>The standard way to indicate to an EJB platform that an entity bean
  has container-managed persistence is to fill the &lt;persistence-type&gt;
  tag of the deployment descriptor with the value "container," and to fill the
  &lt;cmp-field&gt; tag of the deployment descriptor with the list of
  container-managed fields (the fields that the container will have in charge
  to make persistent). The CMP version (1.x or 2.x) should also be specified
  in the &lt;cmp-version&gt; tag. In the textual format of the deployment
  descriptor, this is represented by the following lines:</para>

  <screen>    &lt;persistence-type&gt;container&lt;/persistence-type&gt;
    &lt;cmp-version&gt;2.x&lt;/cmp-version&gt;
    &lt;cmp-field&gt;
      &lt;field-name&gt;fieldOne&lt;/field-name&gt;
    &lt;/cmp-field&gt;
    &lt;cmp-field&gt;
      &lt;field-name&gt;fieldTwo&lt;/field-name&gt;
    &lt;/cmp-field&gt;</screen>

  <para>With container-managed persistence the programmer need not develop the
  code for accessing the data in the relational database; this code is
  included in the container itself (generated by the platform tools). However,
  for the EJB platform to know how to access the database and which data to
  read and write in the database, two types of information must be provided
  with the bean:</para>

  <itemizedlist>
    <listitem>
      <para>First, the container must know which database to access and how to
      access it. To do this, the only required information is the name of the
      DataSource that will be used to get the JDBC connection. For
      container-managed persistence, only one DataSource per bean should be
      used.</para>
    </listitem>

    <listitem>
      <para>Then, it is necessary to know the mapping of the bean fields to
      the underlying database (which table, which column). For CMP 1.1 or CMP
      2.0, this mapping is specified by the deployer in the JOnAS-specific
      deployment descriptor. Note that for CMP 2.0, this mapping may be
      entirely generated by JOnAS.</para>
    </listitem>
  </itemizedlist>

  <para>The EJB specification does not specify how this information should be
  provided to the EJB platform by the bean deployer. Therefore, what is
  described in the remainder of this section is specific to JOnAS.</para>

  <section><info><title>CMP 1.x specifics</title></info>
    

    <para>For CMP 1.1, the bean deployer is responsible for defining the
    mapping of the bean fields to the database table columns. The name of the
    DataSource can be set at deployment time, since it depends on the EJB
    platform configuration. This database configuration information is defined
    in the JOnAS-specific deployment descriptor via the jdbc-mapping element.
    The following example defines the mapping for a CMP 1.1 entity
    bean:</para>

    <screen>    &lt;jdbc-mapping&gt;
      &lt;jndi-name&gt;jdbc_1&lt;/jndi-name&gt;
      &lt;jdbc-table-name&gt;accountsample&lt;/jdbc-table-name&gt;
      &lt;cmp-field-jdbc-mapping&gt;
      &lt;field-name&gt;mAccno&lt;/field-name&gt;
      &lt;jdbc-field-name&gt;accno&lt;/jdbc-field-name&gt;
      &lt;/cmp-field-jdbc-mapping&gt;
      &lt;cmp-field-jdbc-mapping&gt;
      &lt;field-name&gt;mCustomer&lt;/field-name&gt;
      &lt;jdbc-field-name&gt;customer&lt;/jdbc-field-name&gt;
      &lt;/cmp-field-jdbc-mapping&gt;
      &lt;cmp-field-jdbc-mapping&gt;
      &lt;field-name&gt;mBalance&lt;/field-name&gt;
      &lt;jdbc-field-name&gt;balance&lt;/jdbc-field-name&gt;
    &lt;/jdbc-mapping&gt;</screen>

    <para>jdbc_1 is the JNDI name of the DataSource object identifying the
    database. accountsample is the name of the table used to store the bean
    instances in the database. mAccno, mCustomer, and mBalance are the names
    of the container-managed fields of the bean to be stored in the accno,
    customer, and balance columns of the accountsample table. This example
    applies to container-managed persistence. For bean-managed persistence,
    the database mapping does not exist.</para>

    <para>For CMP 1.1, the jdbc-mapping element can also contain information
    defining the behaviour of the implementation of a find&lt;method&gt;
    method (i.e. the ejbFind&lt;method&gt; method, that will be generated by
    the platform tools). This information is represented by the
    finder-method-jdbc-mapping element.</para>

    <para>For each finder method, this element provides a way to define an SQL
    WHERE clause that will be used in the generated finder method
    implementation to query the relational table storing the bean entities.
    Note that the table column names should be used, not the bean field names.
    Example:</para>

    <screen>      &lt;finder-method-jdbc-mapping&gt;
        &lt;jonas-method&gt;
          &lt;method-name&gt;findLargeAccounts&lt;/method-name&gt;
        &lt;/jonas-method&gt;
        &lt;jdbc-where-clause&gt;where balance &amp;gt; ?&lt;/jdbc-where-clause&gt;
      &lt;/finder-method-jdbc-mapping&gt;</screen>

    <para>The previous finder method description will cause the platform tools
    to generate an implementation of ejbFindLargeAccount(double arg) that
    returns the primary keys of the entity bean objects corresponding to the
    tuples returned by the "select ... from Account where balance &gt; ?",
    where '?' will be replaced by the value of the first argument of the
    findLargeAccount method. If several '?' characters appear in the provided
    WHERE clause, this means that the finder method has several arguments and
    the '?' characters will correspond to these arguments, adhering to the
    order of the method signature.</para>

    <para>In the WHERE clause, the parameters can be followed by a number,
    which specifies the method parameter number that will be used by the query
    in this position. Example: The WHERE clause of the following finder method
    can be:</para>

    <screen>      Enumeration findByTextAndDateCondition(String text, java.sql.Date date)

      WHERE (description like ?1 OR summary like ?1) AND (?2 &amp;gt; date)</screen>

    <para>Note that a &lt;finder-method-jdbc-mapping&gt; element for the
    findByPrimaryKey method is not necessary, since the meaning of this method
    is known.</para>

    <para>The datatypes supported for container-managed fields in CMP 1.1 are
    the following:</para>

    <table><info><title>Supported datatypes in CMP 1.1</title></info>
      

      <tgroup cols="3">
        <tbody>
          <row>
            <entry>boolean</entry>

            <entry>BIT</entry>

            <entry>getBoolean(), setBoolean()</entry>
          </row>

          <row>
            <entry>byte</entry>

            <entry>TINYINT</entry>

            <entry>getByte(), setByte()</entry>
          </row>

          <row>
            <entry>int</entry>

            <entry>INTEGER</entry>

            <entry>getInt(), setInt()</entry>
          </row>

          <row>
            <entry>long</entry>

            <entry>BIGINT</entry>

            <entry>getLong(), setLong()</entry>
          </row>

          <row>
            <entry>float</entry>

            <entry>FLOAT</entry>

            <entry>getFloat(), setFloat()</entry>
          </row>

          <row>
            <entry>double</entry>

            <entry>DOUBLE</entry>

            <entry>getDouble(), setDouble</entry>
          </row>

          <row>
            <entry>byte[]</entry>

            <entry>VARBINARY or LONGVARBINARY (1)</entry>

            <entry>getBytes(), setBytes()</entry>
          </row>

          <row>
            <entry>java.lang.String</entry>

            <entry>VARCHAR or LONGVARCHAR (1)</entry>

            <entry>getString(), setString()</entry>
          </row>

          <row>
            <entry>java.lang.Boolean</entry>

            <entry>BIT</entry>

            <entry>getBoolean(), setObject()</entry>
          </row>

          <row>
            <entry>java.lang.Integer</entry>

            <entry>INTEGER</entry>

            <entry>getInt(), setObject()</entry>
          </row>

          <row>
            <entry>java.lang.Short</entry>

            <entry>SMALLINT</entry>

            <entry>getShort(), setObject()</entry>
          </row>

          <row>
            <entry>java.lang.Long</entry>

            <entry>BIGINT</entry>

            <entry>getLong(), setObject()</entry>
          </row>

          <row>
            <entry>java.lang.Float</entry>

            <entry>REAL</entry>

            <entry>getFloat(), setObject()</entry>
          </row>

          <row>
            <entry>java.lang.Double</entry>

            <entry>DOUBLE</entry>

            <entry>getDouble(), setObject()</entry>
          </row>

          <row>
            <entry>java.math.BigDecimal</entry>

            <entry>NUMERIC</entry>

            <entry>getBigDecimal(), setObject()</entry>
          </row>

          <row>
            <entry>java.math.BigInteger</entry>

            <entry>NUMERIC</entry>

            <entry>getBigDecimal(), setObject()</entry>
          </row>

          <row>
            <entry>java.sql.Date</entry>

            <entry>DATE</entry>

            <entry>getDate(), setDate()</entry>
          </row>

          <row>
            <entry>java.sql.Time</entry>

            <entry>TIME</entry>

            <entry>getTime(), setTime()</entry>
          </row>

          <row>
            <entry>java.sql.Timestamp</entry>

            <entry>TIMESTAMP</entry>

            <entry>getTimestamp(), setTimestamp()</entry>
          </row>

          <row>
            <entry>any serializable class</entry>

            <entry>VARBINARY or LONGVARBINARY (1)</entry>

            <entry>getBytes(), setBytes()</entry>
          </row>
        </tbody>
      </tgroup>
    </table>

    <para>(1) The mapping for String will normally be VARCHAR, but will turn
    into LONGVARCHAR if the given value exceeds the driver's limit on VARCHAR
    values. The case is similar for byte[] and VARBINARY and LONGVARBINARY
    values.</para>
  </section>

  <section><info><title>CMP 2.x specifics</title></info>
    

    <para>For a CMP 2.0 entity bean, only the jndi-name element of the
    jdbc-mapping is mandatory, since the mapping may be generated
    automatically (for an explicit mapping definition, refer to the "JOnAS
    Database Mapping" section of the Using CMP2.0 persistence chapter):</para>

    <screen>    &lt;jdbc-mapping&gt;
      &lt;jndi-name&gt;jdbc_1&lt;/jndi-name&gt;
    &lt;/jdbc-mapping&gt;
    &lt;cleanup&gt;create&lt;/cleanup&gt;</screen>

    <para>For a CMP 2.0 entity bean, the JOnAS-specific deployment descriptor
    contains an additional element, cleanup, at the same level as the
    jdbc-mapping element, which can have one of the following values:</para>

    <variablelist>
      <varlistentry>
        <term>removedata</term>

        <listitem>
          <para>at bean loading time, the content of the tables storing the
          bean data is deleted</para>
        </listitem>
      </varlistentry>

      <varlistentry>
        <term>removeall</term>

        <listitem>
          <para>at bean loading time, the tables storing the bean data are
          dropped (if they exist) and created</para>
        </listitem>
      </varlistentry>

      <varlistentry>
        <term>none</term>

        <listitem>
          <para>do nothing</para>
        </listitem>
      </varlistentry>

      <varlistentry>
        <term>create</term>

        <listitem>
          <para>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</para>
        </listitem>
      </varlistentry>
    </variablelist>

    <para>the information defining the behaviour of the implementation of a
    find&lt;method&gt; method is located in the standard deployment
    descriptor, as an EJB-QL query (i.e. this is not JOnAS-specific
    information). The same finder method example in CMP 2.0:</para>

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

    <para>For CMP 2.0, the supported datatypes depend on the JORM mapper
    used.</para>
  </section>
</section>