![]() |
![]() |
Back to the Speedo documentation
The .jdo files describe which classes are the persistent. In the current version of Speedo,the user is required to specify which are the persistent fields for each class. For each class and each field, the user can specify (optionally) extensions for Speedo. Extensions allow the user to choose a mapping of the persistent object into a relational database.
An extension named 'sql-name' permits the user to specify the table name where the persistent class is stored.
<class name="A">
<extension vendor-name="speedo" key="sql-name" value="TABLE_A"/>
</class>
If this extension is not specified, by default the table name is
equal to the name of the class (whithout the package name).
Speedo supports 4 types of identifiers:
<class name="A" identity-type="datastore">
...
</class>
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.
<class name="MyClass" identity-type="datastore">
<datastore-identity strategy="sequence" sequence="my_seq"/>
<field name="other_field"/>
</class>
<class name="MyClass" identity-type="application">
<field name="id" primary-key="true" value-strategy="sequence" sequence="my_seq"/>
<field name="other_field"/>
</class>
<class name="A" identity-type="datastore">
<extension vendor-name="speedo" key="id" value="sequence"/>
</class>
<class name="A" identity-type="datastore">
<extension vendor-name="speedo" key="sql-seq-name" value="SEQ_TABLE_A"/>
</class>
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.
<class name="Invoice" identity-type="application
identity-type="application"">
<field name="number" primary-key="true"/>
</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;
...
}
<class name="A" identity-type="datastore">
<extension vendor-name="speedo" key="id" value="polymorph2l"/>
</class>
All the extension concerning the identifier must be done on
the class tag in the .jdo files.
An extension named 'sql-name' permits to specify the name of the column in the table where the persistent class is stored.
<field name="f1">
<extension vendor-name="speedo" key="sql-name" value="F1_COL"/>
</field>
If this extension is not specified, by default the column
name
is equal to the name of the field.
An extension named 'sql-type' permits to specify the type of the column in table name where the persistent class is stored.
<field name="f1">
<extension vendor-name="speedo" key="sql-type" value="VARCHAR(26)"/>
</field>
If this extension is not specified, by default the column
type
depends on the field type and the used data base.
An extension named 'size' permits to specify the size of primitive field. It permits to define the size of SQL Type.
<field name="f1">
<extension vendor-name="speedo" key="size" value="12"/>
</field>
This property is used for String, BigDecimal or BigInteger
fields. For BigXXX fields, this property represents the number of
digits (integer + decimal). For String fields, this property represents
the maximal String length.
This property is ignored if the sql-type property is specified.
An extension named 'scale' permits to specify the size of primitive field. This value is interesting for a String field. It permits to choose the size of the table column.
<field name="f1">
<extension vendor-name="speedo" key="scale" value="12"/>
</field>
This property is used for BigDecimal fields and it
represents
the number of digits at dot right.
This property is ignored if the sql-type property is specified.
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">And here is the source code of the String2intConverter class
<extension vendor-name="speedo" key="field-converter"
value="com.foo.bar.String2intConverter"/>
</field>
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());
}
}
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>
class A {
private B myB;
...
}
class B {
...
}
A reference field is a field which references a Persistent class and not a multivalued reference (Collection/Set/...). Speedo allows the user to specify which primary key is referenced and therefore where is the foreign key. For a simple reference there are two solutions:
![]() ![]() |
<field name="refToB"> |
This is a foreign key on the primary key of the targeted persistent class (B).
![]() ![]() |
<field name="refToB"> |
This is a foreign key on the primary key of the source persistent class (A).
For more information about the values corresponding to the key
"source-foreign-keys" and "target-foreign-keys", see the section foreign keys declaraction
A "collection" field is a field which references several Persistent classes. Speedo supports several types of structure (java.util.Collection, java.util.Set, java.util.List, []...). Depending of the type of relation (One-Many, Many-Many), a join table can be specified. The join table is optional for a One-Many relation; a foreign key can indeed be defined in the table of the referenced persistent class. On the opposite, a join table is required for a Many-Many relation. The following examples go through the supported cases:
class A {
private Collection myBs;
}
class B {
}
The user does not specify any information about the mapping. By default the relation is stored into a join table. The table and the columns names are chosen by Speedo.
![]() ![]() |
<field name="collectionOfB" persistence-modifier="persistent"> |
class A {
private Collection myBs;
}
class B {
private A myA;
}
The relation is One-Many and there is no join table. The "source-foreign-keys" extension defines the name of the foreign key column in the table of the referenced persistent class.
![]() ![]() |
<class name="A"> |
class A {
private Collection myBs;
}
class B {
}
The relation is Many (no reverse field exists) and there is a join table. The key "join-table" defines the name of the join table. If it is not specified, the default table name is defined as the concatenation of the short class name (without the package name) of the source class with the name of the collection field. The "source-foreign-keys" and "target-foreign-keys" extensions define the column names of the join table.
![]() ![]() |
<field name="collectionOfB" persistence-modifier="persistent"> |
class A {
private Collection myBs;
}
class B {
private Collection myAs;
}
The relation is Many-Many. The key "join-table" defines the name of the join table. If it is not specified the default table name is defined as the concatenation of the short class name (without the package name) of the source class, with the name of the collection field. The "source-foreign-keys" and "target-foreign-keys" extensions define the columns name of the join table.
![]() ![]() |
<class name="A"> |
class A {
private Set strings;
}
The persistent class 'A' references a set of String. The sets of String are stored into the table 'T_SET'.
![]() |
<class name="A" identity-type="datastore"> |
there are two cases of mapping for a Map field.
The example shows a map referenced by the A class ('mapOfBIndexedByString' field). The key of the map is a String value for which the column name can be specified by the 'index-sql-name' extension. The value type of the map is the persistent class B for which the mapping (column name) of the reference can be specified by the 'target-foreign-keys' extension. Finally the map identifier is always the identifier of the reference holder (the 'A' class). The column name of the map identifier can be specified by the extension 'source-foreign-keys'.
<class name="A">
<field name="mapOfBIndexedByString" persistence-modifier="persistent">
<map key-type="java.lang.String" value-type="B"/>
<extension vendor-name="speedo" key="join-table" value="MAP_TABLE_NAME"/>
<extension vendor-name="speedo" key="source-foreign-keys" value="PKA=FKA"/>
<extension vendor-name="speedo" key="target-foreign-keys" value="PKB=FKB"/>
<extension vendor-name="speedo" key="index-sql-name" value="KEY_COL_NAME"/>
<extension vendor-name="speedo" key="index-sql-type" value="VARCHAR(40)"/>
</field>
</class>
The example shows a map referenced by the 'A' class ('mapOfStringIndexedByLong' field). The key of the map is a Long value for which the column name can be specified by the 'index-sql_name' extension'. The value type of the map is a String for which the column name can be specified by the 'element-sql-name' extension. Finally the map identifier is always the identifier of the reference holder (the 'A' class). The column name of the map identifier can be specified by the extension 'source-foreign-keys'.
<class name="A">
<field name="mapOfStringIndexedByLong" persistence-modifier="persistent">
<map key-type="java.lang.Long" value-type="java.lang.String"/>
<extension vendor-name="speedo" key="join-table" value="MAP_TABLE_NAME"/>
<extension vendor-name="speedo" key="source-foreign-keys" value="PKA=FKA"/>
<extension vendor-name="speedo" key="element-sql-name" value="VALUE_COL_NAME"/>
<extension vendor-name="speedo" key="element-sql-type" value="VARCHAR(34)"/>
<extension vendor-name="speedo" key="index-sql-name" value="KEY_COL_NAME"/>
<extension vendor-name="speedo" key="index-sql-type" value="INT8"/>
</field>
</class>
The example shows a map referenced by the A class ('bf1_2_B' field). The key of the map is the 'f1' field of the B class. The value type of the map is the persistent class B.
<class name="A">
<field name="bf1_2_B" persistence-modifier="persistent">
<map key-type="java.lang.String" value-type="B"/>
<extension vendor-name="speedo" key="source-foreign-keys" value="PKA=FKA"/>
<extension vendor-name="speedo" key="key-field" value="f1"/>
</field>
</class>
<class name="B">
<field name="f1"/>
</class>
The second example is the same than the last with a bidirectional relation.
<class name="A">
<field name="bf1_2_B" persistence-modifier="persistent">
<map key-type="java.lang.String" value-type="B"/>
<extension vendor-name="speedo" key="source-foreign-keys" value="PKA=FKA"/>
<extension vendor-name="speedo" key="key-field" value="f1"/>
<extension vendor-name="speedo" key="reverse-field" value="myA"/>
</field>
</class>
<class name="B">
<field name="f1"/>
<field name="myA"/>
</class>
For each field referencing one or several persistent classes, it is possible to specify the reverse field of the relation if it exists. This information is very important: useless I/O are avoided based on the reverse field declaration. The fact that two fields are opposite depends on the semantics of the fields.
<class name="A">
<field name="refToB">
<extension vendor-name="speedo" key="reverse-field" value="refToA"/>
...
</field>
...
</class>
<class name="B">
<field name="refToA"/>
...
</class>
A foreign key declaraction (source or target) defines the column names of the foreign key according to the primary key structure. A foreign key declaraction is comma-separated list of equalities between the name of a primary key column and the name of a foreign key column.
The identifier of the referenced object (A) consists of a single column named "pka" and the column name of the foreign key column is named "fka".
![]() |
<class name="A"> |
The identifier of the referenced object (A) consists of two fields (FIRST_NAME, LAST_NAME). The corresponding names of the composite foreign key are (A_FN, A_LN).
![]() |
<class name="A"> |
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_nameThe actions you can perform on a sequence are:
PersistenceManager pm = pmf.getPersistenceManager();
//first, load the class
pm.getObjectIdClass(Article.class);
//then get the sequence
Sequence s = pm.getSequence(ARTICLE_SEQ);
This section is a summary of the previous ones. It enumerates (alphabetic order) all extensions available in Speedo.
Extension name | node level |
element-sql-name | Map orCollection fields mapping |
element-sql-type | Map or Collection fields mapping |
field-converter | Primitive fields mapping |
id | Class Mapping |
index-sql-name | Map or List fields mapping |
index-sql-type | Map or List fields mapping |
inheritance-filter | Class Mapping |
inheritance-key | Class Mapping |
inheritance-mapping | Class Mapping |
join-table | Map or Collection fields mapping |
key-field | Map fields mapping |
scale | Primitive fields mapping |
size | Primitive fields mapping |
source-foreign-keys | Reference, Collection or Map fields mapping, the foreign key declaraction |
sql-name | Class Mapping or Primitive fields mapping |
sql-seq-name | Class Mapping |
sql-seq-start | Class Mapping |
sql-seq-increment | Class Mapping |
sql-seq-cache | Class Mapping |
sql-type | Primitive fields mapping |
reverse-field | Reference, Collection, or Map fields mapping, the foreign key declaraction |
target-foreign-keys | Reference, Collection or Map fields mapping, the foreign key declaraction |