XML Datastore Mapping

When persisting a Java object to an XML datastore clearly the user would like some control over the structure of the XML document. Here's an example using JDO XML MetaData

<jdo>
    <package name="org.datanucleus.samples.models.company">
        <class name="Person" detachable="true" schema="/myproduct/people" table="person">
            <field name="personNum">
                <extension vendor-name="datanucleus" key="XmlAttribute" value="true"/>
            </field>
            <field name="firstName" primary-key="true"/> <!-- PK since JAXB requires String -->
            <field name="lastName"/>
            <field name="bestFriend"/>
        </class>
    </package>
</jdo>

Things to note :

  • schema on class is used to define the "XPath" to the root of the class in XML. You can also use the extension "xpath" to specify the same thing.
  • table on class is used to define the name of the element for an object of the particular class.
  • column on field is used to define the name of the element for a field of the particular class.
  • XmlAttribute : when set to true denotes that this will appear in the XML file as an attribute of the overall element for the object
  • When a field is primary-key it will gain a JAXB "XmlID" attribute.
  • When a field is a relation to another object (and the field is not embedded) then it will gain a JAXB "XmlIDREF" attribute as a link to the other object.
  • Important : JAXB has a limitation for primary keys : there can only be a single PK field, and it must be a String!
What is generated with the above is as follows

<?xml version="1.0" encoding="UTF-8"?>
<myproduct>
    <people>
        <person personNum="1">
            <firstName>Bugs</firstName>
            <lastName>Bunny</lastName>
            <bestFriend>My</bestFriend>
        </person>        
    </people>

Here's the same example using JDO Annotations

@PersistenceCapable(schema="/myproduct/people", table="person")
public class Person
{
    @XmlAttribute
    private long personNum;

    @PrimaryKey
    private String firstName;

    private String lastName;

    private Person bestFiend;

    @XmlElementWrapper(name="phone-numbers")
    @XmlElement(name="phone-number")
    @Element(types=String.class)
    private Map phoneNumbers = new HashMap();
   
    ...

Here's the same example using JPA Annotations (with DataNucleus @Extension/@Extensions annotations)

TODO Add this example