The standard JDO persistence strategy is to persist an object of a class into its own table. In some situations you may
wish to map the class to a primary table as well as one or more secondary tables. For example when you have a Java class
that could have been split up into 2 separate classes yet, for whatever reason, has been written as a single class, however
you have a legacy datastore and you need to map objects of this class into 2 tables. JDO allows persistence of
fields of a class into
secondary
tables.
The process for managing this situation is best demonstrated with an example. Let's suppose we have a class
that represents a
Printer
. The
Printer
class contains within it various attributes of the
toner cartridge. So we have
package com.mydomain.samples.secondarytable;
public class Printer
{
long id;
String make;
String model;
String tonerModel;
int tonerLifetime;
/**
* Constructor.
* @param make Make of printer (e.g Hewlett-Packard)
* @param model Model of Printer (e.g LaserJet 1200L)
* @param tonerModel Model of toner cartridge
* @param tonerLifetime lifetime of toner (number of prints)
*/
public Printer(String make, String model, String tonerModel, int tonerLifetime)
{
this.make = make;
this.model = model;
this.tonerModel = tonerModel;
this.tonerLifetime = tonerLifetime;
}
}
Now we have a database schema that has 2 tables (PRINTER and PRINTER_TONER) in which to store objects of this class.
So we need to tell DataNucleus to perform this mapping. So we define the MetaData for the
Printer
class like this
<class name="Printer" table="PRINTER">
<join table="PRINTER_TONER" column="PRINTER_REFID"/>
<field name="id" primary-key="true">
<column name="PRINTER_ID"/>
</field>
<field name="make">
<column name="MAKE"/>
</field>
<field name="model">
<column name="MODEL"/>
</field>
<field name="tonerModel" table="PRINTER_TONER">
<column name="MODEL"/>
</field>
<field name="tonerLifetime" table="PRINTER_TONER">
<column name="LIFETIME"/>
</field>
</class>
So here we have defined that objects of the
Printer
class will be stored in the primary table PRINTER.
In addition we have defined that some fields are stored in the table PRINTER_TONER. This is achieved by way of
-
We will store
tonerModel
and
tonerLifetime
in the table PRINTER_TONER. This is achieved
by using <field
table="PRINTER_TONER"
>
-
The table PRINTER_TONER will use a primary key column called PRINTER_REFID. This is achieved by using
<join table="PRINTER_TONER" column="PRINTER_REFID"/>
This results in the following database tables :-
So we now have our primary and secondary database tables. The primary key of the PRINTER_TONER table serves
as a foreign key to the primary class. Whenever we persist a
Printer
object a row will be inserted
into
both
of these tables.
You saw above how we defined the column name that will be the primary key of the secondary table (the
PRINTER_REFID column). What we didn't show is how to specify the name of the primary key constraint to
be generated. To do this you change the MetaData to
<class name="Printer" identity-type="datastore" table="PRINTER">
<join table="PRINTER_TONER" column="PRINTER_REFID">
<primary-key name="TONER_PK"/>
</join>
<field name="id" primary-key="true">
<column name="PRINTER_ID"/>
</field>
<field name="make">
<column name="MAKE"/>
</field>
<field name="model">
<column name="MODEL"/>
</field>
<field name="tonerModel" table="PRINTER_TONER">
<column name="MODEL"/>
</field>
<field name="tonerLifetime" table="PRINTER_TONER">
<column name="LIFETIME"/>
</field>
</class>
So this will create the primary key constraint with the name "TONER_PK".
See also :-