Speedo user manual

 FinalLogo.jpg
 FinalLogo.jpg
  1. Mapping specification in .jdo files
  2. Configuration of the data source access
  3. The Speedo ant task
  4. The PersistenceManagerFactory properties
  5. The configuration files
  6. Mappers, Adapters and persistence support
  7. Logging
  8. Supported types
  9. Application servers integration
  10. Creation of the data structure
  11. Detach/Attach
  12. Fetch Groups

Back to the Speedo documentation




The .jdo files

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.

Class Mapping (Table, identifier)

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).

The identifier of the persistent objects

Speedo supports 4 types of identifiers:

All the extension concerning the identifier must be done on the class tag in the .jdo files.

Primitive fields mapping (Column, SQL type, converter)


Reference fields mapping (foreign key)

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:

For more information about the values corresponding to the key "source-foreign-keys" and "target-foreign-keys", see the section foreign keys declaraction

Collection fields mapping (join table, foreign key)

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:

Example 1:
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">
<collection element-type="B"/>
</field>

Example 2:
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">
<field name="collectionOfB" persistence-modifier="persistent">
<collection element-type="B"/>
<extension vendor-name="speedo" key="source-foreign-keys" value="PKA=FKA"/>
<extension vendor-name="speedo" key="reverse-field" value="thefA"/>
</field>
</class>
...
<class name="B">
<field name="thefA" persistence-modifier="persistent">
<collection element-type="B"/>
</field>
</class>

Example 3:
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">
<collection element-type="B"/>
<extension vendor-name="speedo" key="join-table" value="A_TO_B"/>
<extension vendor-name="speedo" key="source-foreign-keys" value="PKA=FKA"/>
<extension vendor-name="speedo" key="target-foreign-keys" value="PKB=FKB"/>
</field>

Example 4:
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">
<field name="collectionOfB" persistence-modifier="persistent">
<collection element-type="B"/>
<extension vendor-name="speedo" key="join-table" value="A_TO_B"/>
<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="reverse-field" value="collectionOfA"/>
</field>
</class>
...
<class name="B">
<field name="collectionOfA" persistence-modifier="persistent">
<collection element-type="A"/>
</field>
</class>
Example 5:
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">
<field name="id" primary-key="true">
<extension vendor-name="speedo" key="sql-name" value="IDA"/>
</field<>

<field name="strings" persistence-modifier="persistent">
<collection element-type="String"/>
<extension vendor-name="speedo" key="join-table" value="T_SET"/>
<extension vendor-name="speedo" key="source-foreign-keys" value="IDA=IDA"/>
<extension vendor-name="speedo" key="element-sql-name" value="STR_ELEM"/>
</field>
</class>

Map fields mapping (join table, foreign key, key)

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 'join-table' extension. In this case no relationship is possible.


  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 it is possible to have a relationship (reverse field).

Bidirectional relationship (reverse field)

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>


The foreign keys declaraction

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.

Example 1:

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">
<field name="refToB">
<extension vendor-name="speedo"
key="target-foreign-keys"
value="pka=fka"/>
</field>
</class>

Example 2:

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">
<field name="refToB">
<extension vendor-name="speedo"
key="source-foreign-keys"
value="FIRST_NAME=A_FN,LAST_NAME=A_LN"/>
</field>
</class>


All extensions

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


Configuration of the data source access

The speedo.properties file contains a data access section. In this section, the user can choose between the use of a JDBC driver directly or the use of a connection factory.

The Speedo ant task

Description

Enhance an application. Currently this task does not support already enhanced classes: the user must manually remove the .class file of the persistent classes each times this task is used.

Parameters

Attribute Description Required
confFile This is the configuration file of the Speedo enhancer. Usually this file is the speedoc.properties provided in the distribution. No
output Is the location of the .class of the user application. This is also the location where the Speedo files produced for the user persistent class is written. Yes
src Is the location of the source of the user application. Yes
projectName Is the name of the user project. If the user provides JORM persistent descriptor (legacy mapping case) like .pd files, the projectname must be specified and match the project name used in the .pd files. No
classpathref Is the classpath containing Speedo, the user classes, and the configuration files (etc directory). No
logPropFile Is the logging configuration file. It permits to choose another Monolog configuration file than the one provided in the etc directory No
failsonerror indicates if the Speedo enhancer must stop after the first error or try to continue. The default value is true. No

Parameters specified as nested elements


Examples

The following example comes from the examples:

<property name="src" value="${basedir}/src"/>
<property name="build" value="${basedir}/build"/>
<property name="speedoDist" value="${basedir}/../.."/>
...
<path id="classpath">
<pathelement location="${speedoDist}/etc"/>
<pathelement location="${build}"/>
<fileset dir="${speedoDist}">
<include name="speedo.jar"/>
<include name="lib/log/log4j.jar"/>
<include name="lib/jdbc/postgres_jdbc2.jar"/>
</fileset>
</path>
...
<taskdef name ="speedo"
classname="org.objectweb.speedo.ant.AntSpeedo"
classpathref="classpath" />
...
<target="generation">
<delete dir="${build}"/>
<mkdir dir="${build}"/>
<javac srcdir="${src}" destdir="${build}" debug="on">
<classpath refid="classpath"/>
<include name="**/*.java"/>
</javac>
<speedo
confFile="${speedoDist}/etc/speedoc.properties"
output="${build}"
src="${src}"
projectName="invoice"
classpathref="classpath"/>


The PersistenceManagerFactory properties

This section describes the properties of the PersistencManagerFactory. Some properties are not defined in the JDO specification and are specific to Speedo. All of these properties are grouped in the Speedo.properties configuration file.
Property name Description JDO / Speedo Req Value
javax.jdo.PersistenceManagerFactoryClass This property defines the name of the PersistenceManagerFactory class provided by Speddo. This value cannot be changed. JDO Y "org.objectweb.speedo.Speedo"
org.objectweb.speedo.mapperName This property defines the name of mapper which must be used with the database. The default value is 'rdb.automatic'. For more information see the mappers section Speedo Y "rdb.automatic"
or "rdb.postgres"
or "rdb.mysql"
or ...
Speedo alone (no application server)
javax.jdo.option.DriverName This property defines the class name of the jdbc driver JDO Y "org.postgresql.Driver"
or "com.mysql.jdbc.Driver"
or ...
javax.jdo.option.ConnectionURL This property defines the url of the database. JDO Y "jdbc:postgresql:speedoTest"
javax.jdo.option.ConnectionUserName This property defines the user name authorized to access to the database. JDO Y "smith"
javax.jdo.option.ConnectionPassword This property defines the password corresponding to user name authorized to access to the database. JDO Y "myPassword"
org.objectweb.speedo.connection.pool.min This property permits to manage the minimal size of the pool of connection when Speedo uses directly a JDBC driver. The default value is 0. Speedo N a positive integer value
org.objectweb.speedo.connection.pool.max This property permits to manage the maximal size of the pool of connection when Speedo uses directly a JDBC driver. The default value is 20. Speedo N a positive integer value
org.objectweb.speedo.connection.pool.ttl This property defines the time to live of the unsused connection, ie the connection availlable in the pool. The value is declared in millisecond. The 0 value means the resource has no TTL. The 0 value is the default. Speedo N 0 or a positive integer value
org.objectweb.speedo.connection.pool.timeout This property defines the time which the user agrees to wait a free connection from the pool. The value is declared in millisecond. The 0 value means that the user want to wait until a resource has been released. Speedo N 0 or a positive integer value
Integration of Speedo into a J2EE application server
javax.jdo.option.ConnectionFactoryName This property is the jndi name of the connection factory to use to access the data support. JDO Y "myConnFactJndiNAme"
org.objectweb.speedo.jca.TMName This property is the jndi name of a registered transaction manager. For more information see the section about the application server integration Speedo Required when is integrated into an application server "javax.transaction.TransactionManger"
Memory Cache Configuration
javax.jdo.option.IgnoreCache Indicates if queries and extends must ingore the instance modified in memory and not yet committed into the support. The default value is 'true' JDO N 'true' or 'false'
javax.jdo.option.RestoreValues The management of this option is not supported. The only supported value is "false"
javax.jdo.option.RetainValues This property indicates if the peristent object are ketpt in memory at commit time. The default value is 'true' Speedo N 'true' or 'false'
org.objectweb.speedo.cache.policy It defines the replacement politic of the memorry cache. The possible values are: LRU, MRU or FIFO. The default value is LRU Speedo N LRU, MRU or FIFO
org.objectweb.speedo.cache.size This property permits to manage the size of the cache of memory instances. The default value is "nolimit", that means that the cache have not a maximum size. Speedo N "nolimit" or a positive integer value
org.objectweb.speedo.cache.autoCleanSize This property defines the number of cache entry to free when the cache of memory instance is full or when the threshold is reached. The value can be a percent of the maximal cache size (ex: "10%") or an absolute value (ex: "456"). The default value is a percent: "7%". Speedo N a positive integer value between 0 and the cache size or a percent (ex: 12%)
org.objectweb.speedo.cache.autoCleanThreshold Is the number of entries since the cache must try to evict entries. The number of entries to evict is specified by the 'autoCleanSize' property. The possible values are absolute values (234) or a percent of the maximal cache size (75%). By default there is no threshold, then there is no auto cleaning process. Speedo N a positive integer value between 0 and the cache size or a percent (ex: 80%)
Configuration of the Persistence manager pool
org.objectweb.speedo.peristencemanager.pool.min This property permits to manage the minimal size of the pool of PersistenceManager. The default value is 0. Speedo N a positive integer value
org.objectweb.speedo.peristencemanager.pool.max This property permits to manage the maximal size of the pool of PersistenceManager. The default value is "nolimit". Speedo N "nolimit" or a positive integer value
org.objectweb.speedo.peristencemanager.pool.ttl This property defines the time to live of the unsused persistence manager, ie the persistence manager availlable in the pool. The value is declared in millisecond. The 0 value means the resource has no TTL. The 0 value is the default. Speedo N 0 or a positive integer value
org.objectweb.speedo.peristencemanager.pool.timeout This property defines the time which the user agrees to wait a free peristence manager from the pool. The value is declared in millisecond. The 0 value means that the user want to wait until a resource has been released. Speedo N 0 or a positive integer value
Query Management Configuration
org.objectweb.speedo.query.prefetch.query This property permits to desactive the data prefetching on queries. The default value is 'on'. Speedo N 'on' or 'off'
org.objectweb.speedo.query.prefetch.extent This property permits to desactive the data prefetching on extents. The default value is 'on'. Speedo N 'on' or 'off'
org.objectweb.speedo.compiledquery.cache.policy It defines the replacement politic of the compiled query cache. The possible values are: LRU, MRU or FIFO. The default value is LRU Speedo N LRU, MRU or FIFO
org.objectweb.speedo.compiledquery.cache.size This property permits to manage the size of the cache of compiled query instances. The default value is "nolimit", that means that the cache have not a maximum size. Speedo N "nolimit" or a positive integer value
org.objectweb.speedo.compiledquery.cache.autoCleanSize This property defines the number of cache entry to free when the cache of compiled query instances is full or when the threshold is reached. The value can be a percent of the maximal cache size (ex: "10%") or an absolute value (ex: "456"). The default value is a percent: "7%". Speedo N a positive integer value between 0 and the cache size or a percent (ex: 12%)
org.objectweb.speedo.compiledquery.cache.autoCleanThreshold Is the number of entries since the cache must try to evict entries. The number of entries to evict is specified by the 'autoCleanSize' property. The possible values are absolute values (234) or a percent of the maximal cache size (75%). By default there is no threshold, then there is no auto cleaning process. Speedo N a positive integer value between 0 and the cache size or a percent (ex: 80%)
Other properties
javax.jdo.option.Multithreaded Indicates if several threads can manipulate a same PersistenceManager instance in same time (concurrency). The default value is 'false' JDO N 'true' or 'false'
org.objectweb.speedo.mappingStructure This property specifies the behavior of Speedo on the mapping structures (ex SQL tables). The possible behavior are the following:
  • DO_NOTHING : nothing is done. Then the mapping structures already exist at the Speedo starting.
  • CREATE_IF_REQUIRED : The mapping structures are created if they are not already present (default).
  • FORCE_CREATE: The mapping structures are removed (if they already exist), and created.
  • DELETE_DATA: The data present in the mapping structure are removed. Of course if the mapping structure do not exist, it is created.
The default value is CREATE_IF_REQUIRED.
Note: When speedo is integrated into an application server, this property must equal DO_NOTHING. Indeed it is rarely possible to create data structure (SQL relations) inside an XA transaction. If you specify another value, Speedo will force the value to DO_NOTHING and will log a warning about it.
Speedo N DO_NOTHING
or CREATE_IF_REQUIRED
or FORCE_CREATE
or DELETE_DATA
org.objectweb.speedo.txStatistic This property indicates if Speedo must build statistics about the transactions. Speedo N 'true' or 'false'
javax.jdo.option.NontransactionalRead This option is not supported. The value is "false"
javax.jdo.option.NontransactionalWrite This option is not supported. The value is "false"


The configuration files

There are several configuration files provided with Speedo. Indeed Speedo uses several ObjectWeb projects/frameworks. All these configuration files must be available at the root of the classpath. In general most Speedo users only have to manage one file: speedo.properties. This section also describes in the second part the other configuration files.

The configuration file: speedo.properties

This file is used at runtime for the properties of the PersistenceManagerFactory. Therefore this properties file can be loaded into a java.util.Properties instance in order to fetch a PersistanceManagerFactory, as illustrated by the following example:

Properties p = new Properties();
p.load(new FileInputStream("speedo.properties"));
PersistenceManagerFactory pmf = JDOHelper.getPersistenceManagerFactory(p);

The file must be available at the root of the classpath during the runtime. For more information about the propeties of the PersistanceManagerFactory see the section The PersistenceManagerFactory properties of this documentation.

The configuration file: monolog.properties

This file is used to configure logging. It must be available at the root of the classpath during the enhancement and at runtime. For more information see the section The logging in this documentation.

The configuration file: spy.properties

This file is the configuration file of the tool P6Spy permiting to log the SQL call throught the JDBC driver. To activate this logging the user must

The librairies of the p6spy tool are included in the speedo.jar.


The configuration file: julia.cfg

The Speedo implementation respects the component model defined in ObjectWeb: Fractal. Speedo uses Julia as implementation of this model. The julia.cfg file is the configuration file of Julia. It must be available in the classpath (root position) during the enhancement and at runtime.

The configuration file: jorm.properties

To manage the I/O with the support Speedo uses JORM. The jorm.properties file is the JORM configuration file. It defines the supported mapper. It must be available in the classpath during the enhancement and at runtime.

Mappers, Adapters and persistence support

The persistent objects are stored in a persistence support. Thanks to JORM, it is possible to store persistent objects into various types of persistence support. Each persistence support type is represented by a mapper. For a relationnal database the mapper is "rdb". Due to the lack of conformance of JDBC drivers, JORM provides adapters to the JDBC specification for some databases. JORM provides also an automatic mechanism to discover the database product via a metadata provided by connections. If the auto detection fails you have to specify the mapper name mathcing the database product. The following table shows the supported persistence support and the associated mapper names:

Persistence support Mapper name Status
Oracle (<=8.x) rdb.oracle8 OK
Oracle (>=9.x) rdb.oracle OK
PostgresSQL (>= 7.2) rdb.postgres OK
Mysql rdb.mysql OK
MS Sql Server rdb.sqlserver OK
Firebird rdb.firebird Testing
McKoi rdb.mckoi OK
Sap DB rdb.sapdb Testing
Sybase rdb.sybase Testing
Hsql rdb.hsql OK
Driver conform to JDBC specification rdb OK

For more information about the adapters, see the JORM framework. Note that writing an adapter for a new relational database is a very easy task.

How to write a new RdbAdapter ?

The JORM project provides a RdbAdapter module permitting to easily write RdbAdapter. Download the product on the JORM download page.
When your new RdbAdapter works fine, you can integrate the ow_jorm_rdb_adapter.jar into Speedo (lib directory in the distribution).

Logging

Like other ObjectWeb products, Speedo uses a logging API in order to be independant from implementations. Monolog provides wrappers to the usual logging systems like log4j or the logging system of jdk (since 1.4). There is a logging configuration file which does not depends on the logging system. This file is named "monolog.properties". Speedo uses Monolog in the automatic mode:


For logging the SQL requests, see the configuration of the P6Spy tool in the configuration file section.

For more information about Monolog and its configuration file see the Monolog documentation

Supported types

Speedo supports the following types, which means that a persistent field can be declared with one of these types:


Application servers integration

Speedo can be integrated into application servers as a resource adapter (JCA Connector SUN specification). Then, to use Speedo inside an application server, you have to use the rar file provided in the Speedo binary distribution.
To use Speedo in an application server with transactions demarcated by the EJB container, the transaction manager instance (implements javax.transaction.TransactionManager) MUST be registered into JNDI. The JNDI name can be assigned to the property org.objectweb.speedo.jca.TMName in the 'speedo.properties' configuration file. If no name is specified, several attempts are done with classical JNDI names used in some application servers:

Application Server JNDI name of TransactionManager instance
JOnAS javax.transaction.UserTransaction
JBoss java:/TransactionManager
WebLogic javax.transaction.TransactionManager
WebSphere jta/usertransaction
Orion java:comp/UserTransaction


Data structures: Speedo is able, through Jorm, to create the data structure during the first use of a persistent class. But some data support does not permit to create data structures (SQL relations) inside XA transactions. Then Speedo allows only the DO_NOTHING value for the property org.objectweb.speedo.mappingStructure. Then you should read the Creation of the data structure section in order to create the data structure before the application starting.

JOnAS case: In case of you want to integrate Speedo into JOnAS, you have to use compatible versions. Indeed, JOnAS and Speedo use common frameworks (JORM, MEDOR, Perseus) and the some classes are already available in the server. In addition, a small rar file dedicated to JOnAS is also provided with the Speedo distribution.

Creation of the data structure

Speedo through Jorm is able to create automaticaly the data structure on the persistent support. This feature is activated with regards to the property org.objectweb.speedo.mappingStructure of the speedo.properties configuration file.
However in application servers with XA connector some persistent supports are able to create data structure (SQL relations for example) inside an XA transaction. Then we advice you to create data structures before to launch your application. To do this Speedo provides a simple tool class named 'org.objectweb.speedo.tools.DataStructureCreation'. An ant target 'createDataStruct' is also provided inside the build.xml of the speedo distribution and inside the bank example. This target launches the tools class with regards to the following usage:

DataStructureCreation (<class name to initialize> | <.jdo file name>)*
[-Djavax.jdo.option.DriverClassName=<driver class name>]
[-Djavax.jdo.option.ConnectionURL=<database url>]
[-Djavax.jdo.option.ConnectionUserName=<user name>]
[-Djavax.jdo.option.ConnectionPassword=<user password>]

Detach/Attach

Speedo supports detach/attach operations. Once made persistent, an object can be detached from the cache : the user gets a copy of the persistent instance. The copy can be modified either in the same JVM or in a different JVM. Then, the copy can be re-attached: this operation commits the changes on the cache.

To enable such operations on objects, the class must be defined as detachable in the jdo file as follows:

<class name="Player"  identity-type="application" detachable="true">

Detaching instances

The following code sample shows the way to perform a detach operation. This code is based on a Team class containing a collection of Players and a Coach.

//firstly, define a team with 2 players and a coach
Team team = new Team("Bordeaux",null,null);
Collection players = new ArrayList();
Player player1 = new Player("p1", t, 25);
players.add(player1);
Player player2 = new Player("p2", t, 32);
players.add(player2);
team.setPlayers(players);
Coach coach = new Coach("c1", 5, team);
team.setCoach(coach);

//then, get the persistence manager and make the team persistent
PersistenceManager pm = pmf.getPersistenceManager();
pm.currentTransaction().begin();
pm.makePersistent(team);
pm.currentTransaction().commit();

//finally, detach the team
Team copyOfTeam = (Team) ((ProxyManager)pm).detachCopy((Object)team);
pm.close();

The detach operation can be performed indifferently within or outside a transaction. When detaching an object, all references to other persistent objects are replaced by the corresponding detached copies.
Detaching an object not yet persistent makes it persistent before returning a copy of the object. When detaching a persistent-new or a persistent-dirty object, updates of this object are flushed prior to detachment: if the transaction in which the flush is performed rolls back, then the detached copy becomes invalid (no re-attachment is allowed).

Attaching instances

The attach operation has to be performed within an active transaction. When performing an attach, changes made to a copy while detached are applied to the corresponding persistent instance in the cache. If the object being attached is not yet persistent, it is firstly made persistent.

The following code sample shows the way to perform an attach operation. This code is also based on a Team class containing a collection of Players and a Coach.

//firstly, define a team with 2 players and a coach
Team team = new Team("Bordeaux",null,null);
Collection players = new ArrayList();
Player player1 = new Player("p1", team, 25);
players.add(player1);
Player player2 = new Player("p2", team, 32);
players.add(player2);
team.setPlayers(players);
Coach coach = new Coach("c1", 5, team);
team.setCoach(coach);

//then, get the persistence manager and make the team persistent
PersistenceManager pm = pmf.getPersistenceManager();
pm.currentTransaction().begin();
pm.makePersistent(team);
pm.currentTransaction().commit();

//detach the team and modify the detached copy
Team copyOfTeam = (Team) ((ProxyManager)pm).detachCopy((Object)team);
copyOfTeam.getCoach().setExperience(99);

//finally attach the team
pm.currentTransaction().begin();
Team attachedTeam = (Team) ((ProxyManager)pm).attachCopy((Object)copyOfTeam,false);
pm.currentTransaction().commit();
pm.close();

The object returned by the attach method is the persistent object corresponding to the detached instance.


Fetch Groups

Definition

A fetch group defines a particular loaded state for an object graph. It specifies fields to be loaded for all the instances in the graph.
Speedo uses fetch groups for detach, refresh and retrieve operations.

Predefined fetch groups

  Within Speedo, four fetch groups are predefined:
  1. default:
  2.             The default group is based on the "default-fetch-group" attribute value of the field definition. It is composed of all the fields defined as belonging to the default fetch group in the jdo file.
                 The default group can be redefined as a normal fetch group by the user in the jdo files.
  3. values:
  4.             The values group is composed of all fields that are included in the default group by default (primitive fields, String, etc...).
                 As the default group, the values group can also be redefined by the user in the jdo files.
  5. none:
  6.             The none group contains only primary key fields.
  7. all:
  8.             The all group contains all fields in the class.

Defining fetch groups

   The user can define his own fetch groups within the jdo files associated to the used objects by the application.
   The examples are based on the following classes:

public class Person{
String name;
int age;
Address address;
Set children;
}

public class Address{
String street;
String city;
Country country;
}

public class Country{
String code;
String name;
}

           With the following fetch group, the name, age and address of all the persons being detached (resp. refreshed, retrieved) will be detached (resp. refreshed, retrieved). The children field                 will not be loaded:
   
<class name="Person" ...>
...
<fetch-group name="myFirstFG">
<field name="name"/>
<field name="age"/>
<field name="address"/>
</fetch-group>
...
</class>
            A dot-separated expression identifies a "to be loaded" field reachable from the class by navigating a reference:

<class name="Person" ...>
...
<fetch-group name="referenceFG">
<field name="address.country.code"/>
</fetch-group>
...
</class>
            Activating this fetch group, the address field will be first loaded with only the country field. And then, the country field will be loaded with only the code field.
            Note: Via the use of JORM, Speedo loads all the primitive fields of a class even if they are not defined in the active fetch group. This means that in the previous example, fields street             and city of the address will be loaded as the code field for the country.
            A fetch group definition can contain nested fetch group(s): the named nested fetch group(s) are to be included to define the graph to load. Nested fetch group elements are limited to                 olny the name attribute. It is not permitted to nest entire fetch group definitions.

<class name="Person" ...>
...
<fetch-group name="nestedFG">
<fetch-group name="values"/>
<field name="children"/>
</fetch-group>
...
</class>
            The name and age fields will be loaded because of the nested fetch group "values" and the children field will also be loaded.
            Recursive fetch group references are controlled by the depth attribute. If no depth is defined, the whole graph of instances reachable from this field will be fetched. It is the case for the             previous example: the children of the person detached, refreshed or retrieved will be loaded, as the children of these children, and etc...
   
<class name="Person" ...>
...
<fetch-group name="depthFG">
<fetch-group name="default"/>
<field name name="address"/>
<field name="children" depth="1"/>
</fetch-group>
...
</class>
           The name, age, address will be loaded and it will be the same for the children of the person being detached, refreshed or retrieved. The children of the children will not be loaded.

            If one or more depths have been specified then the largest depth is used unless one of the depths has not beeen specified (unlimited overrides other depth specifications).
            For a field within a fetch group, an additional fetch group may be specified: this fetch group is then considered to be active just for the loading of the field.
   
<class name="Person" ...>
...
<fetch-group name="list">
<field name="name"/>
<field name name="age"/>
</fetch-group>

<fetch-group name="detail">
<fetch-group name="default"/>
<field name="address"/>
<field name="children" fetch-group="list"/>
</fetch-group>
...
</class>
            Let's consider that the active fetch group is the "detail" fetch group. The fields name, age and address will be loaded for the person being detached, refreshed or retrrieved. For the field             children, the fetch group "list" will be used: the name and age of each child will be loaded.

    The example below is based on the following classes:

public class Node{
String name;
Map edges; //name -> EdgeWeight
}

public class EdgeWeight{
int weight;
}
            For maps, "#key" or "#value" may be appended to the name of the map field to navigate the key or value respectively (e.g. to include a field of the key  class or value class in the fetch             group). If nothing is appended, both the key and the value will be loaded.
            Note: Via the use of JORM, Speedo only supports primitive fields as key of the map. Moreover, the key of an element of a map is always loaded. This means that, even if the #key is                 not specified in the fetch group, the key will be loaded.

<class name="Node" ...>
...
<fetch-group name="keyValue">
<field name="edges#key"/>
<field name="edges#value"/>
</fetch-group>

<fetch-group name="keyOnly">
<field name="edges#key"/>
</fetch-group>
...
</class>
           If the "keyValue" fetch group is active, both keys and values of elements in the map of the node object will be loaded.
           If the "keyOnly" fetch group is active, only keys of elements in the map of the node object will be loaded. The value field is set to null for each element of the map.

Managing fetch groups

    Fetch groups are activated using methods of the FetchPlan interface. The mutating methods of this interface return the FetchPlan instance to allow method chaining.
    Once defined in the jdo files, fetch groups can be activated in the proxy manager at runtime as described below:
  1. Instanciate a fetch plan. When instanciated, a fetch plan contains the "default" fetch group. A fetch plan can contain many fetch groups.
  2. Add and remove the fetch group(s) to define the fetch plan wanted.
  3. Set the fetch plan defined to the proxy manager. (Step 2 and 3 can be shifted.)
PersistenceManager pm = pmf.getPersistenceManager();
FetchPlan fp = new SpeedoFetchPlan();
fp.addGroup("detail").removeGroup("default"); //only the detail fg is active
((ProxyManager)pm).setFetchPlan(fp);
    The application is then ready to detach, refresh and retrieve instances using the fetch groups.
    Note: if no fetch plan has been set for the proxy manager, the default fetch group is used. A SpeedoFetchPlan(String fgName) constructor is also available to instanciate the fetch plan with     the fgName fetch group (the default fetch group is not active then).