15.5. Datastore Identity
Prev | Chapter 15. Mapping Metadata | Next

## 15.5. Datastore Identity

In a relational database, a table's primary key is the set of columns whose values uniquely identify a row within that table. JDOR requires all persistent class tables to have primary keys, though these keys may be logical (i.e. there is no requirement that the database enforce the uniqueness of the primary key column values).

Under JDO's application identity type, the primary key field mappings are enough to infer the primary key columns of each class' table. Classes that use datastore identity, on the other hand, must describe their tables' primary key using the `datastore-identity` mapping element. This element is the first child of the `class` element, and has the following attributes:

- `strategy`: A strategy for auto-generating the primary key value. JDOR recognizes the strategies below, and vendors may define additional proprietary strategies.

  - `native`: Leave primary key value generation to the JDOR implementation. This is the default strategy if none is specified.

  - `sequence`: Use a sequence to generate the primary key value. This strategy is used in conjunction with the `sequence` attribute below.

  - `autoassign`: The database automatically assigns a primary key value on insert. This might be accomplished with an auto-increment column or with database triggers.

    When you use the `autoassign` strategy, calling `JDOHelper.getObjectId` or `PersistenceManager.getObjectId` with a persistent-new object may cause the `PersistenceManager` to flush. The `PersistenceManager` will insert the new object and retrieve the database-assigned primary key value so that it can return the new instance's proper persistent identity.

  - `identity`: The primary key column is managed by the database as an identity type.

  - `increment`: The JDOR implementation will select the highest current primary key value, and increment it by one to get the primary key value for the next inserted object.

  - `uuid-string`: Generates a 128-bit UUID unique within the network and represents the result as a 16-character string. For more information on UUIDs, see the IETF UUID draft specification at: http://www1.ics.uci.edu/~ejw/authoring/uuid-guid/

  - `uuid-hex`: Same as `uuid-string`, but represents the UUID as a 32-character hexadecimal string.

  Not all standard datastore identity strategies will be implemented by all vendors. For example, there is no way for a vendor that uses numeric datastore identity values to support the `uuid-string` and `uuid-hex` strategies.

  | Note
  Kodo supports the `native`, `sequence`, `autoassign`, and `identity` datastore identity strategies. Kodo treats `identity` and `autoassign` equivalently, as they are the same for most databases. Before using the `identity` or `autoassign` strategies, see Section 5.3.3, “Autoassign / Identity Strategy Caveats”. Though Kodo does not define any custom datastore identity strategies, you can take over the generation of datastore identity values by using the `sequence` strategy in conjunction with a sequence that has a custom `factory-class`.

- `sequence`: Names a sequence to use to generate the primary key value. When this attribute is specified, the `strategy` attribute described above automatically defaults to a value of `sequence`.

  | Note
  If you specify `system` as the `sequence` attribute value, Kodo will use the system sequence defined by the `kodo.Sequence` configuration property instead of looking for a named sequence.

- `column`: The name of the primary key column.

In place of the `column` attribute above, you can embed `column` elements within the `datastore-identity` element. This allows you to define multiple datastore identity columns for implementations that require it, and to specify additional attributes aside from the column name. Section 15.6, “Column” discusses the `column` element in detail.

The diagram below now includes primary key columns for our model's tables. The primary key column for `LineItem` uses nonstandard type `INTEGER64`, and the `Magazine.isbn` field is mapped to a `CHAR(15)` column instead of a `VARCHAR(255)` column, which is the default for string fields. We do not need to point out either one of these oddities to the JDOR implementation for runtime use. If, however, we want to use the JDOR implementation to create our tables for us, it needs to know about any desired non-default column types. Therefore, the example following the diagram includes this data in its encoding of our mappings. The example also includes the mappings of primary key fields in our application identity classes; we will get to field mapping in Section 15.11, “Field Mapping”.

Example 15.3. Datastore Identity Mapping

    <?xml version="1.0"?>
    <orm>
        <package name="org.mag">
            <sequence name="ArticleSeq" datastore-sequence="ART_SEQ"/>
            <class name="Magazine" table="MAG">
                <field name="isbn">
                    <column name="ISBN" jdbc-type="char" length="15"/>
                </field>
                <field name="title" column="TITLE"/>
                ...
            </class>
            <class name="Article" table="ART">
                <field name="id" column="ID"/>
                ...
            </class>
        </package>
        <package name="org.mag.pub">
            <sequence name="AuthorSeq" factory-class="Author$SequenceFactory"/>
            <class name="Company" table="COMP">
                <datastore-identity column="CID" strategy="autoassign"/>
                ...
            </class>
            <class name="Author" table="AUTH">
                <datastore-identity sequence="AuthorSeq">
                    <column name="AID" sql-type="INTEGER64"/>
                </datastore-identity>
                ...
            </class>
        </package>
        <package name="org.mag.subscribe">
            <sequence name="ContractSeq" strategy="transactional"/>
            <class name="Contract">
                ...
            </class>
            <class name="Subscription" table="CNTRCT.SUB">
                <field name="Contract.id" column="ID"/>
                ...
            </class>
            <class name="LifetimeSubscription">
                ...
            </class>
            <class name="TrialSubscription" table="CNTRCT.TRIAL_SUB">
                ...
            </class>
            <class name="Subscription$LineItem" table="CNTRCT.LINE_ITEM">
                <field name="Contract.id" column="ID"/>
                ...
            </class>
        </package>
    </orm>

Prev | Up | Next
15.4. Class Table | Home | 15.6. Column