JDO Guides : Secondary Tables

It may be that you wish to store some fields of a class in a separate table from the main table the class is mapped to. We can perform this mapping using the JDO metadata. This can be seen through an example

public class Printer
    String make;
    String model;
    String tonerModel;
    int tonerLifetime;

    public Printer(String make, String model, String tonerModel, int tonerLife)
        this.make = make;
        this.model = model;
        this.tonerModel = tonerModel;
        this.tonerLifetime = tonerLife;


We now need to specify which fields we want to store in any secondary tables. To do this we can define the metadata like this

<?xml version="1.0"?>
    "-//Sun Microsystems, Inc.//DTD Java Data Objects Metadata 2.0//EN" 
    <package name="mydomain">
        <class name="Printer" table="PRINTER">           
                <column name="ID"/>
            <join table="TONER">
                <column name="ID"/>
            <field name="make"/>
            <field name="model"/>
            <field name="tonerModel" table="TONER"/>
            <field name="tonerLifetime" table="TONER"/>

With this we have stated that the fields make and model will be stored in the default table, that we named PRINTER, and that tonerModel and tonerLifetime we be stored in the table TONER. The tables will both store the unique identity assigned to the objects we persist, in this case we have specified the column name ID for both tables, though we would usually only do this when working to an existing schema. When we retrieve any of our stored objects the tables will be joined automatically by matching the identities.

We can see how this works in more detail by setting the query logging to DEBUG (set log4j.category.DataNucleus.Query=DEBUG , in your log4j.properties file). We can retrieve all of our stored Printer objects by performing the following query

Query q = pm.newQuery(Printer.class);
List<Printer> list = (List<Printer>)q.execute();

Now if we look in our log file we can see how this has been converted into the appropriate query language for our datastore. With an RDBMS datastore using SQL, for example, we get

SELECT FROM mydomain.Printer Query compiled to datastore query 
"SELECT 'mydomain.Printer' AS NUCLEUS_TYPE,`A0`.`MAKE`,`A0`.`MODEL`,`A1`.`TONER_MODEL`,

So we can see that in this case an INNER JOIN was performed using the ID columns as expected.

This tutorial was provided by a DataNucleus user Tom Robson