JDO : Serialising Fields

JDO provides a way for users to specify that a field will be persisted serialised. This is of use, for example, to collections/maps/arrays which typically are stored using join tables or foreign-keys to other records. By specifying that a field is serialised a column will be added to store that field and the field will be serialised into it.

JDO's definition of serialising encompasses several types of fields. These are described below

Perhaps the most important thing to bear in mind when deciding to serialise a field is that that object must implement java.io.Serializable.


Serialised Collections

Applicable to RDBMS, HBase, MongoDB

Collections are usually persisted by way of either a join table, or by use of a foreign-key in the element table. In some situations it is required to store the whole collection in a single column in the table of the class being persisted. This prohibits the querying of such a collection, but will persist the collection in a single statement. Let's take an example. We have the following classes


and we want the animals collection to be serialised into a single column in the table storing the Farm class, so we define our MetaData like this

<class name="Farm" table="FARM">
    <datastore-identity column="ID"/>
    <field name="name" column="NAME"/>
    <field name="animals" serialized="true">
        <collection element-type="Animal"/>
        <column name="ANIMALS"/>
    </field>
</class>
<class name="Animal">
    <field name="name"/>
    <field name="type"/>
</class>

So we make use of the serialized attribute of <field>. This specification results in a table like this


Provisos to bear in mind are

  • Queries cannot be performed on collections stored as serialised.

There are some other combinations of MetaData tags that result in serialising of the whole collection in the same way. These are as follows

  • Collection of non-persistable elements, and no <join> is specified. Since the elements don't have a table of their own, the only option is to serialise the whole collection and it appears as a single BLOB field in the table of the main class.
  • Collection of persistable elements, with "embedded-element" set to true and no <join> is specified. Since the elements are embedded and there is no join table, then the whole collection is serialised as above.

See also :-

Serialised Collection Elements

Applicable to RDBMS

Collections are usually persisted by way of either a join table, or by use of a foreign-key in the element table. In some situations you may want to serialise the element into a single column in the join table. Let's take an example. We have the same classes as in the previous case and we want the animals collection to be stored in a join table, and the element serialised into a single column storing the "Animal" object. We define our MetaData like this

<class name="Farm" table="FARM">
    <datastore-identity column="ID"/>
    <field name="name">
        <column name="NAME"/>
    </field>
    <field name="animals" table="FARM_ANIMALS">
        <collection element-type="Animal" serialised-element="true"/>
        <join column="FARM_ID_OID"/>
    </field>
</class>
<class name="Animal">
    <field name="name"/>
    <field name="type"/>
</class>

So we make use of the serialized-element attribute of <collection>. This specification results in tables like this


Provisos to bear in mind are

  • Queries cannot be performed on collection elements stored as serialised.

See also :-


Serialised Maps

Applicable to RDBMS, HBase, MongoDB

Maps are usually persisted by way of a join table, or very occasionaly using a foreign-key in the value table. In some situations it is required to store the whole map in a single column in the table of the class being persisted. This prohibits the querying of such a map, but will persist the map in a single statement. Let's take an example. We have the following classes


and we want the children map to be serialised into a single column in the table storing the ClassRoom class, so we define our MetaData like this

<class name="ClassRoom">
    <field name="level">
        <column name="LEVEL"/>
    </field>
    <field name="children" serialized="true">
        <map key-type="java.lang.String" value-type="Child"/>
        <column name="CHILDREN"/>
    </field>
</class>
<class name="Child"/>

So we make use of the serialized attribute of <field>. This specification results in a table like this


Provisos to bear in mind are

  • Queries cannot be performed on maps stored as serialised.

There are some other combinations of MetaData tags that result in serialising of the whole map in the same way. These are as follows

  • Map<non-persistable, non-persistable>, and no <join> is specified. Since the keys/values don't have a table of their own, the only option is to serialise the whole map and it appears as a single BLOB field in the table of the main class.
  • Map<non-persistable, persistable>, with "embedded-value" set to true and no <join> is specified. Since the keys/values are embedded and there is no join table, then the whole map is serialised as above.

See also :-

Serialised Map Keys/Values

Applicable to RDBMS

Maps are usually persisted by way of a join table, or very occasionaly using a foreign-key in the value table. In the join table case you have the option of serialising the keys and/or the values each into a single (BLOB) column in the join table. This is performed in a similar way to serialised elements for collections, but this time using the "serialized-key", "serialized-value" attributes. We take the example in the previous section, with "a classroom of children" and the children stored in a map field. This time we want to serialise the child object into the join table of the map

<class name="ClassRoom">
    <field name="level">
        <column name="LEVEL"/>
    </field>
    <field name="children" table="CLASS_CHILDREN">
        <map key-type="java.lang.String" value-type="Child" serialized-value="true"/>
        <join column="CLASSROOM_ID"/>
        <key column="ALIAS"/>
        <value column="CHILD"/>
    </field>
</class>
<class name="Child"/>

So we make use of the serialized-value attribute of <map>. This results in a schema like this


Provisos to bear in mind are

  • Queries cannot be performed on map keys/values stored as serialised.

See also :-


Serialised persistable Fields

Applicable to RDBMS, HBase, MongoDB

A field that is a persistable object is typically stored as a foreign-key relation between the container object and the contained object. In some situations it is not necessary that the contained object has an identity of its own, and for efficiency of access the contained object is required to be stored in a BLOB column in the containing object's datastore table. Let's take an example. We have the following classes


and we want the teacher object to be serialised into a single column in the table storing the ClassRoom class, so we define our MetaData like this

<class name="ClassRoom">
    <field name="level">
        <column name="LEVEL"/>
    </field>
    <field name="teacher" serialized="true">
        <column name="TEACHER"/>
    </field>
</class>

So we make use of the serialized attribute of <field>. This specification results in a table like this


Provisos to bear in mind are

  • Queries cannot be performed on persistable objects stored as serialised.

Serialised Reference (Interface/Object) Fields

Applicable to RDBMS

A reference (Interface/Object) field is typically stored as a foreign-key relation between the container object and the contained implementation of the reference. In some situations it is not necessary that the contained object has an identity of its own, and for efficiency of access the contained object is required to be stored in a BLOB column in the containing object's datastore table. Let's take an example using an interface field. We have the following classes


and we want the teacher object to be serialised into a single column in the table storing the ClassRoom class, so we define our MetaData like this

<class name="ClassRoom">
    <field name="level">
        <column name="LEVEL"/>
    </field>
    <field name="teacher" serialized="true">
        <column name="TEACHER"/>
    </field>
</class>
<class name="Teacher">
</class>

So we make use of the serialized attribute of <field>. This specification results in a table like this


Provisos to bear in mind are

  • Queries cannot be performed on Reference (Interface/Object) fields stored as serialised.

See also :-

Serialised Field to Local File

Applicable to RDBMS

If you have a non-relation field that implements Serializable you have the option of serialising it into a file on the local disk. This could be useful where you have a large file and don't want to persist very large objects into your RDBMS. Obviously this will mean that the field is no longer queryable, but then if its a large file you likely don't care about that. So let's give an example

@PersistenceCapable
public class Person
{
    @PrimaryKey
    long id;

    @Persistent
    @Extension(vendorName="datanucleus", key="serializeToFileLocation"
        value="person_avatars")
    AvatarImage image;
}

Or using XML

<class name="Person">
    ...
    <field name="image" persistence-modifier="persistent">
        <extension vendor-name="datanucleus" key="serializeToFileLocation"
            value="person_avatars"/>
    </field>
</class>

So this will now persist a file into a folder person_avatars with filename as the String form of the identity of the owning object. In a real world example you likely will specify the extension value as an absolute path name, so you can place it anywhere in the local disk.