Speedo user manual: Edition of .jdo file(Mapping)

 FinalLogo.jpg
 FinalLogo.jpg

This page will help you to edit JDO 2 persistent descriptors: .jdo files. It is structured as the following outline :

  1. Introduction to .jdo files
  2. Class declaration
  3. The identifier of the persistent objects
  4. Primitive fields mapping
  5. Direct reference to persistent instance
  6. Multivalued fields (Collection, Set, List, Map)
    1. Reference to several primitive values
    2. Reference to several persistent instances (non prmitive)
    3. List fields
    4. Map fields
  7. Bidirectional relationship
    1. One-One Bidirectional relationship
    2. One-Many Bidirectional relationship
    3. Many-Many Bidirectional relationship
  8. Class mapped over several tables
  9. Inheritance
  10. Index, unique
  11. Sequence

Back to the Speedo documentation




  1. Introduction
  2. The .jdo files describe the classes of your application are persistent. JDO specification requires the definition of one .jdo file per java package or one .jdo file per persistent class. In first case the file name of the .jdo file must be 'package.jdo' whereas in the second case the name of the .jdo file must be the name of the unique persistent class described.

    For each class the developer must specify the persistent field. By default primitive fields (int, Integer, String, ...) are persistent. Since JDO 2.0 the O/R mapping is standard. In previous version of specification the mapping was defined with the help of extensions specific to each JDO provider.

    Below is an example of .jdo file describing the persistence of the class 'simpleclass.Address'. This class has 5 persistent fields.

    <!DOCTYPE jdo PUBLIC "-//Sun Microsystems, Inc.//DTD Java Data Objects Metadata 2.0//EN" "jdo2.dtd">
    <jdo>
        <package name="simpleclass">
            <class name="Address" identity-type="application" table="SIMPLE_ADDRESS">
                <field name="street" primary-key="true" column="STREET"/>
                <field name="city" column="CITY"/>
                <field name="state" column="STATE"/>
                <field name="zip" column="ZIPCODE"/>
                <field name="deliveryInstructions">
                    <column name="DELIV_INS" sql-type="VARCHAR(50)"/>
                </field>
            </class>
        </package>
    </jdo>
    

  3. Class declaration
  4. The 'class' xml node defines a persistent class as sub node of 'package'. At class level the 'table' attribute specifies the main table where the class is stored.

            <class name="Address" table="SIMPLE_ADDRESS">
                ...
            </class>
    

    If no table are specified, Speedo will compute automaticaly a table name from the short name of the persistent class.

  5. The identifier of the persistent objects
  6. A persistent class must have an identifier format. The JDO specification defines two kinds of identifier:

    Speedo supports 4 types of identifiers:

    1. application, single field: The identifier is one field of the persistent class. This field must have a primitive type (int, long, String, Byte, ....). This identifier mode does not permit inheritance. To use this identifier, you have to specifiy identity-type="application" and to specify the attribut primary-key="true" on the field which is the identifer.
      <class name="Invoice" identity-type="application">
          <field name="number" primary-key="true"/>
      </class>

    2. application, composite identifier on fields: The identifier is composed of fields of the persistent class (one or several). These fields must have a primitive type (int, long, String, Byte, ....). This identifier mode will permit inheritance. To use this identifier you have to specifiy identity-type="application" and one of these solutions:
      • You specify the attribut primary-key="true" on each field composing the identifier. Then an user class identifier is generated by Speedo (class name + "Id").
      • You specify a value for the attribut 'objectid-class'. All fields of the object identifer class must be public and must be also fields of the persistent class.

      <class name="Address" identity-type="application
      identity-type="application"
      objectid-class="invoice.AddressID">

      <field name="name" primary-key="true"/>
      <field name="street" primary-key="true"/>
      <field name="town" primary-key="true"/>
      </class>

      class AddressID {
      public String name;
      public String street;
      public String town;

      ...
      }

    3. datastore, native:

      These identifier values are computed from a persistent generator managed by Speedo and stored in the database. The identifier is a single long. The 20 high bits identify the class whereas the 44 low bits identify the object instance. This identifier supports inheritance. To use this identifier you only have to specifiy any identity type because 'datastore' is the default value.

      <class name="A">
          ...
      </class>

      This naming is interesting if your relational database does not support sequence or if you have inheritance in your data model.
      In details: The identifier generators are persistent into the table 'jf_longgen' whereas the class identifiers are stored into the table 'jf_classid'.

      Even if the identifier is allocated by a speedo you can want to have access to the identifier field. You can declare a persistent field as primary which the type is long or java.lang.Long. If you choose 'long' the null references are stored with the -1 value. If you choose 'java.lang.Long' the null references are with the NULL SQL value.



    4. datastore, sequence: These identifier values are computed from a speedo sequence. There are three ways to define it:
      • Using a datastore identity (you cannot access the identifier hidden field which is created by Speedo)

        <class name="MyClass" identity-type="datastore">
            <datastore-identity strategy="sequence" sequence="my_seq"/>
            <field name="other_field"/>
        </class>
      • Using a sequence value strategy (you define your identifier field and you can access it):

        <class name="MyClass" identity-type="application">
            <field name="id" primary-key="true" value-strategy="sequence" sequence="my_seq"/>
            <field name="other_field"/>
        </class>
      • Using the Speedo extension with datastore identifier management (deprecated):
        This identifier type is provided by relational databases (except MySQL). This identifier is based on a SQL sequence. This identifier type does not support inheritance except if you specify an identifier allocator able to add a discrimant value into the long value (in the low or high bits). There are several ways to use this identifier type:
        • By specifying 'identity-type="datastore"' and the extension 'id' with the value 'sequence'. In this case the sequence name is calculated from the table name or the class name.
          <class name="A" identity-type="datastore">
          <extension vendor-name="speedo" key="id" value="sequence"/>
          </class>
        • By specifying 'identity-type="datastore' and the extension 'sql-seq-name' as value of the sequence name.
          <class name="A" identity-type="datastore">
          <extension vendor-name="speedo" key="sql-seq-name" value="SEQ_TABLE_A"/>
          </class>
        In addition it is possible to specify some creation parameter for the SQL sequence:
        • sql-seq-start is the initial value of the sequence. Hence it is the first identifier to allocate. This value must be a long. the default value is 0.
        • sql-seq-increment is the value added at each allocation of identifier. This value must be a long. The default value is 1.
        • sql-seq-cache is the number of identifiers which must be cached by the JDBC driver. This feature avoids I/O to the database at each allocation time. Therefore the use of a cache increase performances. This value must be a long. By default no caching is done.
      <>
      Identifier allocator:The user can specify a class implementing the interface 'org.objectweb.jorm.facilty.naming.rdb.SequenceIdAllocator'. containing only the long allocateId(long seqValue, Object key) method. To specify the use of an identifier allocator, you have to put the class name as value associated to the key 'sql-seq-allocator'.

      Even if the identifier is allocated by a sequence you can want to have access to the identifier field. You can declare a persistent field as primary which the type is long or java.lang.Long. If you choose 'long' the null references are stored with the -1 value. If you choose 'java.lang.long' the null references are with the NULL SQL value.

    NOTE: The other datastore identity types (autoassign, increment, uuid-string and uuid-hex) will be supported later.

  7. Primitive fields
  8. With Speedo a field is a primitive field when its types is a primitive type or a wrapper to a primitive type. Here is the list of field types manages as primitive type in Speedo:

    Its is not required to declare primitive fields in the .jdo file, excepted if you want to specify constraints or column name. In the .jdo file a persistent field is declared thanks to the 'field' xml node (sub node of 'class' node) Here a simple example.

    <field name="myField"/>

    JDO 2 specification defines several attributs to declare constraints:

    In relational support a primitive field is mapped over a single column. The column definition can be specified with the sub xml node column as shwon by the following example:

    <field name="myField">
    	<column name="MY_COL" sql-type="VARCHAR(28)"/>
    </field>

    On this column tag, the 'sql-type', the 'size' or the 'scale' can be specified.
    The 'sql-type' is the SQL column type.
    The 'size' attribut is useful for String, BigDecimal or BigInteger fields. For BigXXX fields, this property represents the number of digits (integer + decimal). For String fields, the attribut represents the maximal String length. This attribut is ignored if the sql-type attribut is specified.
    The 'scale' attribut is useful for float and double field. This attribut is ignored if the sql-type attribut is specified.

    'field-converter' extension

    An extension named 'field-converter' permits to change the usual translation between the memory type and the data support type for a primitive field. For example, if the user has a legacy relationnal database, it can map an integer field into a String (VARCHAR on a RDB). To do this, the user must implement the org.objectweb.speedo.api.UserFieldMapping interface provided by Speedo. This implementation is able to convert a memory value to a data store value and reversly. Finally, the user must indicate, as value of the extenstion 'field-converter', the class name of the interface implementation.

    <field name="f1">
    <extension vendor-name="speedo" key="field-converter"
    value="com.foo.bar.String2intConverter"/>
    </field>

    And here is the source code of the String2intConverter class:

    package com.foo.bar;
    public class String2intConverter implements UserFieldMapping {
    public Class getStorageType() {
    return String.class;
    }
    public Class getMemoryType() {
    return Integer.TYPE;
    }
    public Object toMemory(Object storagevalue) {
    return Integer.valueOf((String) storagevalue)
    }
    public Object toStorage(Object memoryvalue) {
    return (memoryvalue == null ? null : memoryvalue.toString());
    }
    }

    'user-cache' extension

    The extension named 'user-cache' permits to specify that a primitive field is a part of an unique index in an user cache. For more details about the user cache feature see the corresponding chapter. The value of the extension is the name of the user cache. If the index of the cache is composite, you simply have to specify the extension for each field with the same user cache name. A class can have several unique indexes.

    The following examples a class containg 4 fields. The fields 'id' is the identifier (primary key). The couple (f1,f2) is a secondary key. The field 'f3' is another key.

    <field name="id" primary-key="true"/>
    <field name="f1">
    <extension vendor-name="speedo" key="user-cache"
    value="myCache1"/>
    </field>
    <field name="f2">
    <extension vendor-name="speedo" key="user-cache"
    value="myCache1"/>
    </field>
    <field name="f3">
    <extension vendor-name="speedo" key="user-cache"
    value="myCache2"/>
    </field>

  9. Direct reference to persistent instance
  10. A reference field is a field which references one persistent instance. In case of there is no bidirectional relationship (no reverse field), the reference to the other persistent class is mapped over column in tables of the field owner class. In other words the foreign-key is in the table of class owning the reference. The column corresponding to the foreign key can be defined with 'column' attribute or sub xml node. Below is a simple example of showing a reference from the class 'A' to the class 'B'. The class 'A' is stored on the 'TA' table whereas the class 'B' is stored on the 'TB' table.

    class A {
        String myIda;
        B myB;
    }
    class B {
        long myIdb;
    }


    Below is the corresponding jdo file part describing both persistent class and the mapping of the reference:

    <class name="A" identity-type="application" table="TA">
        <field name="myIda" primary-key="true" column="IDA"/>
        <field name="myB" column="FK_IDB"/>
    </class>
    <class name="B" identity-type="application" table="TB">
        <field name="myIdb" primary-key="true" column="IDB"/>
    </class>

    The 'column' defines the name of the foreign key column (FK_IDB). As the referenced class has an identified composed of a single column (IDB), the correspondance is implicit.
    If the identifier of the referenced class is composite, you have to specify the target column for each column of the foreign key as shown by the following example:

    <class name="A" identity-type="application" table="TA">
        <field name="myIda" primary-key="true" column="IDA"/>
        <field name="myB">
            <column name="FK_IDB1" target="IDB1"/>
            <column name="FK_IDB2" target="IDB2"/>
        </field>
    </class>
    <class name="B" identity-type="application" table="TB">
        <field name="myIdb1" primary-key="true" column="IDB1"/>
        <field name="myIdb2" primary-key="true" column="IDB2"/>
    </class>

  11. Multivalued fields (Collection, Set, List, Map)
  12. A multivalued field is a field referencing several primitive values or several persistent instances (mixing is forbiden). Speedo supports several types of structure (java.util.Collection, java.util.Set, java.util.List, ...). This chapter is divided in several parts corresponding to the content of multivalued field and the type of structure.

    Reference to several primitive values

    When a multivalued field references a collection of primitive values, an additional table is required. This table must be join to the main table of the field owner. Currently, Speedo supports only joins based on the identifier. Here is an example of a 'A' persistent class references a set of String value.

    class A {
    	String ida;
    	Collection strings;
    }
    <class name="A" >
        <field name="ida" primary-key="true" column="IDA"/>
        <field name="strings" table="T_SET">
            <collection element-type="String"/>
            <element column="STR"/>
            <join column="FKIDA"/>
        </field>
    </class>

    The sets of String are stored into the 'T_SET' table. The column corresponding to the element is STR. The join to this table is based on the identifier of the class. The foreign key column is 'FKIDA'. If the identifier of the owner class is composite the join declaration is a bit more complex:

    <class name="A" >
        <field name="ida1" primary-key="true" column="IDA1"/>
        <field name="ida2" primary-key="true" column="IDA2"/>
        <field name="strings" table="T_SET">
            <collection element-type="String"/>
            <element column="STR"/>
            <join>
                </column name="FK_IDA1" target="IDA1"/>
                </column name="FK_IDA2" target="IDA2"/>
            </join>
        </field>
    </class>

    For each column of the foreign key, the target column has to be specified.

    Reference to several persistent instances (non prmitive)

    This case is the same than a reference to several primitive value except for the element definition. Be careful, if this field composes a bidirectional relation ship, you have to read the dedicated chapter about bidirectional relationship. Here is an example of a class 'A' having a collection of 'B' instance.

    class A {
    	String ida;
    	Collection myBs;
    }
    class B {
    	long idb;
    }


    <class name="A" >
        <field name="ida" primary-key="true" column="IDA"/>
        <field name="myBs" table="TAB">
            <collection element-type="B"/>
            <element column="FKIDB"/>
            <join column="FKIDA"/>
        </field>
    </class>
    <class name="B" >
        <field name="idb" primary-key="true" column="IDB"/>
    </class>

    The sets of B are stored into the 'TAB' table. The column corresponding to the reference to B instances is FKIDB. This column implicitly references the identifier column of the referenced class (B). The join to the TAB table is based on the identifier of the class 'A'. The foreign key column is 'FKIDA'. If the identifier of the referenced class is composite the element declaration is a bit more complex:

    <class name="A" >
        <field name="ida" primary-key="true" column="IDA"/>
        <field name="myBs" table="TAB">
            <collection element-type="B"/>
            <element>
                 <column name="FKIDB1" target="IDB1">
                 <column name="FKIDB2" target="IDB2">
            </element>
            <join column="FKIDA"/>
        </field>
    </class>
    <class name="B" >
        <field name="idb1" primary-key="true" column="IDB1"/>
        <field name="idb2" primary-key="true" column="IDB2"/>
    </class>

    For each column of the foreign key, the target column has to be specified.

    List fields

    Map fields

    A map defines an association between keys and their corresonding values. Speedo supports only primitive types as map key. In the other hand, the value of the map can be a primitive values or instances of a persistent class.

    When the value type is primitive, the only possible mapping is to have a table dedicated for the map storing.
    The example shows a map referenced by the 'A' class ('mapOfStringIndexedByLong' field). The key of the map is a Long value. The value type of the map is a String. Finally the join to the map table is based on the identifier of 'A' class.

    class A {
        long ida;
        Map<B,String>  mapOfBIndexedByString;
    }
    <class name="A">
        <field name="ida" primary-key="true" column="IDA"/>
        <field name="mapOfStringIndexedByLong" persistence-modifier="persistent"
            table="MAP_LONG_TO_STRING">
            <map key-type="java.lang.Long" value-type="java.lang.String"/>
            <join column="FKIDA"/>
            <key column="LONG_KEY_COL"/>
            <value column="STRING_VALUE_COL"/>
        </field>
    </class>

    When value type are instance of persistent class, there are two cases of mapping for a Map field.

    1. Firstly the "map" field is stored into an intermediate table, which the name can be defined by the 'table' attribut on field.

      The example below shows a map referenced by the A class ('mapOfBIndexedByString' field). The map is stored on table 'MAP_TABLE_NAME'. The keys of the map are string valuevalue whereas the values are instances of B persistent class. The join to the map table is based on the identifier of 'A' class.

      class A {
          long ida;
          Map<B,String>  mapOfBIndexedByString;
      }
      class B {
      	long idb;
      }
      <class name="A">
          <field name="ida" primary-key="true" column="IDA"/>
          <field name="mapOfBIndexedByString" persistence-modifier="persistent"
              table="MAP_TABLE_NAME">
              <map key-type="java.lang.String" value-type="B"/>
              <join column="FKIDA"/>
              <key column="STRING_KEY_COL"/>
              <value column="FKIDB"/>
          </field>
      </class>
      <class name="B" >
          <field name="idb" primary-key="true" column="IDB"/>
      </class>

    2. Secondly the map field is stored into the table of the persistent class stored in value. In this case the key of the map is a field of the class, and there is a bidirectional relationship between both classes.
      The example shows a map referenced by the A class. The value type of the map is the persistent class B. The key of the map is the 'f1' field value of the B class.

      <class name="A">
          <field name="f1_to_B" persistence-modifier="persistent"> mapped-by="myA">
              <map key-type="java.lang.String" value-type="B"/>
              <extension vendor-name="speedo" key="key-field" value="f1"/>
          </field>
      </class>
      <class name="B">
          <field name="idb" column="IDB"/>
          <field name="f1"/>
          <field name="myA" column="FKIDA"/>
      </class>

  13. Bidirectional relationship
  14. When two classes have reference to each other, you have a bidirectional relationship. In many cases, both fields share the same data structure in the data support. For this reason, the JDO specification permits to define only the mapping in one side of the raltion. The second one is defined from the mapping of the first. For one-one or one-Many relations, a common advice is to define the mapping of the reference having the foreign key. For Many-Many relation, the mapping can be defined on side that you want.
    In addition to define the mapping only one side, Speedo supports coherency of relationship. This means that when you modify a field value, the reverse field is automatically updated in order to keep the coherence of the relation type.
    This chapter has sections dedicated to each type of relation ship in order to explain their mapping.

    One-One Bidirectional relationship

    One-One relationship can use only one or two foreign keys. In first case you have to define the foreign column on the side of the foreign key. In the other reference, you simply specifies the 'mapped-by' attribut with the name ofthe reverse field.
    Here is an example of a One-One relationship between 'A' and 'B' classes. The foreign key 'FKIDB' is in the 'TA' table. The mapping of the field 'myA' is defined from the mapping of the field 'myB'.

    class A {
        long ida;
        B myB;
    }
    class B {
        long idb;
        A myA;
    }



    <class name="A" table"TA">
        <field name="ida" column="IDA"/>
        <field name="myB"> column="FKIDB"/>
    </class>
    <class name="B" table"TB">
        <field name="idb" column="IDB"/>
        <field name="myA" mapped-by="myB"/>
    </class>


    Here is another example of a One-One relationship between 'A' and 'B' classes. Here there is two foreign keys, one in each table.

    class A {
        long ida;
        B myB;
    }
    class B {
        long idb;
        A myA;
    }


    <class name="A" table"TA">
        <field name="ida" column="IDA"/>
        <field name="myB"> column="FKIDB"/>
    </class>
    <class name="B" table"TB">
        <field name="idb" column="IDB"/>
        <field name="myA" column="FKIDA/>
    </class>

    One-Many Bidirectional relationship

    With a One-Many bidirectional relationship, the usual mapping is to have one foreign key in the Many side of the relation. We strongly advice you to define the mapping of the One side with simple columns and to specify the 'mapped-by' on the Many side.
    Here is an example of One-Many relation ship between 'A' and 'B' classes. The 'A' class references a collection of 'B' instances whereas the 'B' class reference a single A instance.

    class A {
        long ida;
        Collection myBs;
    }
    class B {
        long idb;
        A myA;
    }


    <class name="A" table="TA">
        <field name="ida" column="IDA"/>
        <field name="myBs" mapped-by="myA">
            <collection element-type="B"/>
        </field>
    </class>
    <class name="B" table="TB">
        <field name="idb" column="IDB"/>
        <field name="myA" column="FKIDA"/>
    </class>

    Many-Many Bidirectional relationship

    With a Many-Many bidirectional relationship, there is one join table and two foreign keys. The mapping is defined on only one side and the mapped-by attribut is used on the other.
    Here is an example of Many-Many bidirectional relationship between the 'A' and 'B' classes. The mapping is only defined on the reference 'myAs' (table name and both foreign keys).

    class A {
        long ida;
        Collection myBs;
    }
    class B {
        long idb;
        Collection myAs;
    }


    <class name="A" table="TA">
        <field name="ida" column="IDA"/>
        <field name="myBs" table="TAB">
            <collection element-type="B"/>
            <join column="FKIDA"/>
            <element column="FKIDB"/>
        </field>
    </class>
    <class name="B" table="TB">
        <field name="idb" column="IDB"/>
        <field name="myA" mapped-by="myBs">
            <collection element-type="A"/>
        </field>
    </class>

  15. Class mapped over several tables
  16. In case of legacy database schema, sometimes it is interesting to map a persistent over several table. Currently Speedo supports this mapping if the join conditions between tables are the identifier columns of the persistent class.
    Below is an example of a persistent class (Address) stored on 3 tables (SECONDTAB_ADDRESS_MAIN, SECONDTAB_ADDRESS_DELIV, SECONDTAB_ADDRESS_MAP).

    <class name="Address" identity-type="application" table="SECONDTAB_ADDRESS_MAIN">
        <join table="SECONDTAB_ADDRESS_DELIV">
            <column name="FK_D_STREET" target-column="STREET"/>
        </join>
        <field name="street" primary-key="true" column="STREET"/>
        <field name="city" column="CITY"/>
        <field name="state" column="STATE"/>
        <field name="zip" column="ZIPCODE"/>
        <field name="deliveryInstructions" table="SECONDTAB_ADDRESS_DELIV">
            <column name="DELIV_INS" sql-type="VARCHAR(50)"/>
        </field>
        <field name="signatureRequired" table="SECONDTAB_ADDRESS_DELIV"/>
        <field name="mapJPG" table="SECONDTAB_ADDRESS_MAP" column="IMAGE">
            <join column="FK_M_STREET" target-column="STREET"/>
        </field>
    </class>

    The fields 'street', 'city', 'state' and 'zip' are stored on the main table (SECONDTAB_ADDRESS_MAIN). The fields 'deliveryInstructions' and 'signatureRequired' are stored on the table 'SECONDTAB_ADDRESS_DELIV'. Finally the field 'signatureRequired' is stored on the table 'SECONDTAB_ADDRESS_MAP'. The example shows both ways (at class level or at field level) to declare the secondary tables and their join. When secondary table is declared at field level, any other field of the class can be stored on this secondary table.

  17. Inheritance
  18. An inheritance tree can be mapped according to several strategy: filtered, horizontal, vertical. Here is an example of the inheritance strategies:

    class A {
        String id;
        String f1;
    }
    class B extends A {
        String f2;
    }
    Name Description Schemas of both classes
    Filtered A single table contains all fields of all classes.
    Horizontal Each class has its own table containing its fields and its inherited fields.    
    Vertical Each class has its own table containing field of the current class. This table has a join to the parent table. Inherited fields are not mapped again because parent table is used.    

    The parent class and inheritance strategy have to be defined in the .jdo file as shown by this example.

    <class name="B" persistence-capable-superclass="A">
        <inheritance strategy="superclass-table"/>
        ...
    </class>

    Currently Speedo supports only two strategies of inheritance mapping: Filtered and horizontal. The next chapters describes details of each strategy.

    Filtered mapping

    This strategy stores the sub class in the same table than its parent. The common table is defined at parent level. Field mapping is defined once time.

    <class name="A" table="TA">
        <inheritance strategy="new-table"/>
        <field name="id" primary-key="true" column="ID"/>
        <field name="f1" column="F1"/>
    </class>
    <class name="B" persistence-capable-superclass="A">
        <inheritance strategy="superclass-table"/>
        <field name="f2" column="F2"/>
    </class>

    To distringuish class of instances a discriminator is required. There are three possibles case for this discriminator:

    If you use the speedo identifier (long value auto computed), no discriminator is required because it is included into the long value. It is the best choice when identifier structure is not defined by the application.

    Horizontal mapping

    With the horizontal strategy, each class has its table. Currently Speedo supports this strategy only if Speedo manages the identifier it already includes a discriminator. With this stategy, the sub class must define the mapping of inherited field. To distinguish fields, you have to add the class name as prefix (fully qualified name if not in the same package).

    <class name="A" table="TA">
        <inheritance strategy="new-table"/>
        <field name="f1" column="F1"/>
    </class>
    <class name="B" persistence-capable-superclass="A" table="TB">
        <inheritance strategy="new-table"/>
        <field name="A.f1" column="F1"/>
        <field name="f2" column="F2"/>
    </class>

    Vertical mapping

    With the vertical mapping strategy, each class has its table. The table contains columns of new fields (not inherited fields). Currently Speedo supports this strategy only if Speedo manages the identifier or if application identifier includes a discriminator. Indeed this mapping choice is the more efficient when you have reference to parent class, because it avoids to look for in all tables corresponding to subclass.

    <class name="A" table="TA">
        <inheritance strategy="new-table"/>
        <field name="f1" column="F1"/>
    </class>
    <class name="B" persistence-capable-superclass="A" table="TB">
        <inheritance strategy="new-table"/>
        <field name="A.f1" column="F1"/>
        <field name="f2" column="F2"/>
    </class>

  19. Index, unique, foreign key declarations
  20. The JDO 2 specification permits to declare constraints and indexes in relational database. For the three type of declaration there are the same ways to define them.

    Note: Currently Speedo supports only indexes and unique constraint.

  21. Sequence
  22. The sequence element identifies a sequence number generator that can be used for several purposes:

    A sequence is defined at the package level. The list of attributes to define your sequence is as follows:

    <package ...>
    <sequence name="my_seq" strategy="transactional" datastore-sequence="name_of_datastore_seq"/>
    ...
    </package>

    You can retrieve the sequences using the getSequence(String name) method on the persistent manager:

    Sequence s = pm.getSequence(SEQ_NAME); //SEQ_NAME is the fully qualified name of the sequence : package + seq_name
      The actions you can perform on a sequence are:


      Note: be sure that one of the class of the package the sequence belongs to has been loaded before using the sequence.

    PersistenceManager pm = pmf.getPersistenceManager();
    //first, load the class
    pm.getObjectIdClass(Article.class);
    //then get the sequence
    Sequence s = pm.getSequence(ARTICLE_SEQ);