http://www.datanucleus.org Andy has posted 14 posts at DZone. You can read more from them at their website. View Full User Profile

What's New in JDO 2.3

05.21.2009
| 8412 views |
  • submit to reddit

Java Data Objects (JDO) is a specification for Java persistence that started in 2000, with 2 major releases JDO1 (2002 under JSR0012) and JDO2 (2006 under JSR0243). It was placed under Apache in 2005 and is the rare example of a specification that has undergone continual improvement during its lifetime, for the last 4 years being developed totally in the open, accepting input from everyone. Most recently it was provided as an integral part of the Google AppEngine for Java

JDO 2.3 was started in October 2008, and encompasses additions to the specification in the areas of a metadata API, an enhancer API, addition of cancel/timeout control to queries, and addition of control to the locking of objects when read.

DataNucleus AccessPlatform 1.1.3 was recently released with support for these new features, and Apache JDO has just released JDO 2.3 "early access". In this article we describe what's new and an overview of how to use it.

 

Metadata API

To persist Java objects you need to specify which classes are persistable, and how they are persisted. This was traditionally handled using XML configuration. With the advent of JDK1.5, annotations were added as another possible way of defining such information. JDO 2.3 takes this further and provides a Metadata API, allowing runtime definition. This is of particular use for systems that don't know at application startup which classes should be persistable, maybe because the class hasn't been written yet.

To demonstrate the Metadata API, lets assume that we have a PersistenceManagerFactory created for our datastore. So we request a new Metadata object.

PersistenceManagerFactory pmf = JDOHelper.getPersistenceManagerFactory(props);
JDOMetaData jdomd = pmf.newMetadata();

So we can now start defining the metadata for the package/class(es) we want to persist. The Metadata is structured in a similar way to the XML DTD/XSD. So let's add a class

ClassMetadata cmd = jdomd.newClassMetadata("test.Client");
cmd.setTable("CLIENT").setDetachable(true).setIdentityType(javax.jdo.annotations.IdentityType.DATASTORE);
cmd.setPersistenceModifier(javax.jdo.metadata.ClassPersistenceModifier.PERSISTENCE_CAPABLE);

So we have a class test.Client using datastore-identity, that is detachable, and is persisted to a table CLIENT. As you can see, you can chain setters for convenient coding.

InheritanceMetadata inhmd = cmd.newInheritanceMetadata();
inhmd.setStrategy(javax.jdo.annotations.InheritanceStrategy.NEW_TABLE);
DiscriminatorMetadata dmd = inhmd.newDiscriminatorMetadata();
dmd.setColumn("disc").setValue("Client").setStrategy(javax.jdo.annotations.DiscriminatorStrategy.VALUE_MAP);
dmd.setIndexed(Indexed.TRUE);

VersionMetadata vermd = cmd.newVersionMetadata();
vermd.setStrategy(javax.jdo.annotations.VersionStrategy.VERSION_NUMBER).setColumn("version");
vermd.setIndexed(Indexed.TRUE);

So we will use "new-table" inheritance for this class, and it will have a discriminator stored in column disc of type "value-map". The class will also be versioned, using column version, that is indexed. All of this was for the class as a whole, so let's look at the fields/properties of the class.

FieldMetadata fmd = cmd.newFieldMetadata("name");
fmd.setNullValue(javax.jdo.annotations.NullValue.DEFAULT).setColumn("name").setIndexed(true).setUnique(true);

So we have a field name that is persisted into column name, and is unique and indexed. The API metadata components all follow the DTD as stated earlier, so if our field was a collection we could then define CollectionMetadata below it.

The only thing left to do is register the metadata with the PersistenceManagerFactory, like this

pmf.registerMetadata(jdomd);

and any contact with the class will now persist according to this metadata.

You can similarly browse already-registered metadata using

ComponentMetadata compmd = pmf.getMetadata("mydomain.MyClass");

Note that you cannot change already registered metadata with JDO 2.3. You can view the Javadocs for the Metadata API here.

 

Enhancer API

JDO implementations typically (but aren't compelled to) include a bytecode enhancement step, allowing for efficient change detection of objects. While the Metadata API above is very useful, if we just define metadata for a class we still need to enhance the class using this metadata. This is where the Enhancer API comes in. To start we need to get a JDOEnhancer

JDOEnhancer enhancer = JDOHelper.getEnhancer();

and now that we have the enhancer and want to enhance our class above so we need to register our new metadata with it (generate the metadata as shown above)

enhancer.registerMetadata(jdomd);

Now we can handle the enhancement using a separate class loader if required (for example if the classes were defined dynamically, e.g by ASM)

enhancer.setClassLoader(myClassLoader);

Finally we select what to enhance, and perform the enhancement

String[] classes = {"test.Client"};
enhancer.addClasses(classes);
enhancer.enhance();

So the class is now enhanced and is ready for use. You can view the Javadocs for the Enhancer API here.

 

Query Cancel/Timeout API

On occasions a query may be inefficient, or may suffer from problems in the underlying datastore, and so we don't want to affect the application. In this case it would make sense to have control over a timeout for the query, or be able to cancel it. JDO 2.3 introduces the Query cancel/timeout control, via the following new methods to javax.jdo.Query

void setTimeoutMillis(Integer interval);
Integer getTimeoutMillis();
void cancelAll();
void cancel(Thread thread);

So we have the ability to cancel a query as required, or just let it timeout.

 

Control of read objects locking

When we are using datastore (pessimistic) transactions it often doesn't make sense to just lock all objects read in the transaction. For this reason JDO 2.3 introduces control over which objects are locked and which aren't.

In metadata for each class you can specify the "serialize-read" setting. True will mean that objects of this type will be locked when read.

On a Transaction you can override the metadata settings via the following method

void setSerializeRead(Boolean serialize);
Boolean getSerializeRead();

On a Query you can override the metadata and Transaction settings via the following method

void setSerializeRead(Boolean serialize);
Boolean getSerializeRead();

This concludes our simple overview of JDO2.3. We hope you enjoy using it, and if you have ideas of where you would like JDO to be taken in the future please address them to the Apache JDO project

 

Published at DZone with permission of its author, Andy Jefferson.

(Note: Opinions expressed in this article and its replies are the opinions of their respective authors and not those of DZone, Inc.)

Tags:

Comments

Jose Maria Arranz replied on Fri, 2009/05/22 - 2:38am

First of all, congratulations for the good work on JDO and to keep alive this great technology for "real" transparent persistence!

On question: does DataNucleus provide a "memory database"? That is, persistent objects persisted in memory. This feature can be useful for:

* Prototypes, demos etc: to avoid the burden of setting up a real database.

* Object management in memory: for instance JDOQL used to search objects in memory, transactions used to rollback changes to the previous state of an object tree.

Saludos

 

 

Andy Jefferson replied on Fri, 2009/05/22 - 2:51am in response to: Jose Maria Arranz

DataNucleus doesn't "provide" a database of its own, but we use HSQLDB embedded for our testing, hence no need to set up a database, just put the jar in the CLASSPATH. [H2, or Derby in embedded mode would serve equally well]

DataNucleus also allows the ability to query over a Collection of candidates (provided by the user) satisfying a query filter, hence no call to the datastore would be needed in that case. See http://www.datanucleus.org/products/accessplatform_1_1/jdo/jdoql_inmemory.html

Saludos

Jose Maria Arranz replied on Fri, 2009/05/22 - 4:08am

Fine.

Anyway it would be a nice feature, especially in-memory transactions and queries, most of the work is already done :)

 

Piotr Kochanski replied on Fri, 2009/05/22 - 5:53am

I am totally unfamiliar with JDO, but I use JPA a lot. Are there any advantages of using JDO over JPA, are there any usecases where the former technology is better. How these two technologies relate in fact. I've found a comparison http://www.jpox.org/docs/1_2/jdovsjpa.html which seems to show that JDO is superior when it comes to functionality. Why JPA is much more popular then JDO and was choosen to be standard JEE persistence technology?

Andy Jefferson replied on Fri, 2009/05/22 - 6:08am

Why not read the real FAQ ? This concentrates on the real facts, and technical issues that a user should be concerned with, as opposed to the one on the SUN website which brings in politics and corporate behaviour.

JDO JPA FAQ

JDO is datastore-agnostic whilst JPA is totally oriented to RDBMS. JDO also has a more complete ORM definition than JPA (despite JPA catering only for RDBMS). The Apache JDO website has 3 pages showing the differences also.

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.