3.3 Defining a Class
The first step in using JDO is to create a persistence-capable Java class. For the purposes of the examples in this book, it is assumed that byte code enhancement is being used, so all that is needed is a Java class. The following code snippet shows the code for a class called Author, which represents the author of a book:
package com.corejdo.examples.model; public class Author { private String name; public Author (String name) { this.name = name; } protected Author () {} public String getName () { return name; } public void setName (String name) { this.name = name; } }
This class is relatively simply with just one string field. JDO can, of course, support much more than this; see Section 3.9 for more details on what is supported.
Note that the fields of the class are declared as private. Unlike other approaches to object persistence, JDO does not require fields of classes to be declared public. In fact, JDO places few constraints on the definition of the Java classes themselves.
There is one requirement, however; JDO requires that a persistence-capable class have a no-arguments constructor. This constructor does not need to be declared public, it just needs to be accessible to the class itself and to any potential subclasses. If there are no subclasses, it can be declared as private. However, if there are subclasses, it should be declared as protected or packaged so that it is accessible from the subclasses.
The no-args constructor is used by the JDO runtime to create empty instances of the class prior to retrieving its fields from the datastore.
To make the Author class persistence-capable, it must be compiled and passed to the byte code enhancement tool. Before this can be done, however, an XML file must be created that contains the JDO metadata for the class.
3.3.1 JDO metadata
For each persistence-capable class, JDO requires additional metadata. This metadata is specified in an XML file. The metadata is primarily used when making a Java class persistence-capable (by byte code, source enhancement, or code generation). However, it is likely also to be used by a JDO implementation at runtime.
By convention, these files have a .jdo suffix. Each class can have a metadata file, in which case the file is named after the class itself, or there can be one metadata file per package, in which case the file is named package.jdo. The metadata files should be accessible at runtime as resources via the class loader that loaded the persistence-capable Java class.
For the Author class, a file called Author.jdo would be located in the same directory as the Author class file. This allows the byte code enhancement process and JDO implementation to easily locate it as follows:
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE jdo SYSTEM "jdo.dtd"> <jdo> <package name="com.corejdo.examples.model"> <class name="Author"/> </package> </jdo>
Alternately, the metadata for this class could be located in a file called package.jdo that would be located in the com/corejdo/examples/model directory. This file could contain metadata on all the classes in the "model" package (and subpackages), not just the Author class. Appendix B provides a detailed overview of the syntax for the JDO metadata. For this class, however, all that is needed is to specify the package name and class name.
When the Author source and metadata files are ready, they can be passed to the byte code enhancement tool. This takes care of implementing the persistence-capable contract. As an example, if using the JDO reference implementation (RI), the Author class would be compiled as normal using javac and then the RI byte code enhancement tool would be invoked from the command line as follows:
javac Author.java java com.sun.jdori.enhancer.Main Author.class Author.jdo
By default, the RI enhancement tool updates the Author byte code in place, and the original Author.class file is replaced with an enhanced one.
The initial JDO 1.0 specification didn't actually mandate the location and name of the XML metadata files. To aid in portability, the 1.0.1 maintenance revision to the specification changed this to what has just been described.
Prior to this revision, the name of a metadata file that contained multiple classes was the package name itself with a .jdo suffix, and it was located in the directory containing the package directory. In the Author example above, it would have been called model.jdo and would have been located in the com/corejdo/examples/ directory. Some JDO implementations may still use this naming convention.
3.3.2 Mapping a class to the datastore
JDO does not define how to specify how the fields of a class should be mapped to the underlying datastorefor example, if using a relational database, what tables and columns should be usednor does it define how the datastore schema should be created in the first place.
All this is datastore and JDO-implementation specific. A JDO implementation provides the necessary tools to allow a developer to define a mapping between the persistence-capable classes and the underlying datastore and to define the required datastore schema.
As an example, a JDO implementation on top of a relational database might use the "vendor-extensions" element in the JDO metadata for a class to specify table and column names or define how field values should be stored. An implementation using an object database or a flat file might require only the Java classes and nothing more.