Skip to content

ActiveObjects 0.8 Released

22
Mar
2008

Happy Easter everyone, we’ve got a new release!  ActiveObjects 0.8 is simmering at low heat (and footprint) on the servers even as I type.  This is probably the most significant milestone we’ve released thus far in that the 1.0 stream is now basically feature-complete.  I won’t be adding any new features to this release, just polishing and testing the heck out of the old ones.  We’ve already got a suite of 91 tests and I’ve got lots of ideas for more.  Expect this framework to get very, very stable in the next few months.

Features

Despite an annoyingly cramped schedule in the last couple months, I have managed to implement a few long-requested features.  The big ticket item for this release is pluggable cache implementations.  For those of you not “in the know”, ActiveObjects has a multi-tiered cache system composed of several layers and delegates.  This isn’t entirely unusual for an ORM, which is why I hadn’t mentioned it before.  The three basic layers:

  • Entity Cache - A SoftReference map from id/type pairs to actual entity values.  This means that if you run a query which returns an entity for people {id=1} and then run a second query which returns an entity for the same row, the two instances will be identical.  This is what enables the additional cache layers to function properly (and it saves on memory).
  • Value Cache - This is where all the field values for a given row are stored.  This will store both field values from the database as well as entity values (corresponding to foreign key fields).  Each entity has a separate instance of this cache.  Most of the memory required by ActiveObjects is taken up here.  With a long-running application, quite a bit of the database can actually get paged into memory.  This is a really good thing, since it drastically reduces round-trips to the database.  Thanks to the SoftReference(s) in the entity cache, running out of memory due to stale cache entries isn’t a problem.
  • Relations Cache - This is probably the most complex of all of the cache layers.  This cache literally caches any one-to-one, one-to-many or many-to-many result sets and spits them out on demand.  This reduces round-trips still more to the point where certain applications can be running completely from memory, even querying on complex relations.  This in and of itself isn’t that complex; the hard part is knowing when to expire specific cache entries.  This cache layer is essentially three different indexes to the same data, allowing cache expiry for a number of different circumstances.  Naturally, these structures don’t represent well as a single map of key / value pairs.  (more on this in a bit)

As of the 0.8 release, the value cache and relations cache layers have been unified under a single controller.  They’re still separate caches, but this unification allows for something I’ve been wanting to implement since 0.2: Memcached support.

High-volume applications often run into the problem of limited memory across the various server nodes.  Solutions like Terracotta can help tremendously, but unfortunately this doesn’t solve everything.  One answer is to provide every node in the cluster with a shared, distributed, in-memory map of key / value pairs.  This allows the application to page data into cluster memory and retrieve it extremely quickly.  Memcached is effectively this.  Naturally, it would be very useful if an ORM could automatically make use of just such a distributed memory cache and thus share cached rows between nodes.  Hibernate has had this for a long time, and now ActiveObjects does as well.

By making use of the MemcachedCache class in the activeobjects-memcached module (separate from the main distribution), it is possible to point ActiveObjects at an existing Memcached cluster and cause it to store the value cache there, rather than in local memory.  Once the relevant call has been made to EntityManager (setting up the cache), all cached rows will be stored in Memcached and shared between every instance of ActiveObjects running in your cluster.

Caveats

Of course, nothing is perfect.  For the moment, the major issues is that the relations cache doesn’t work properly against Memcached.  I had originally planned to just release it running against the local RAM, but this causes issue with proper cache expiry.  As such, the relations cache is disabled when running ActiveObjects against Memcached.  This doesn’t really impair functionality other than forcing ActiveObjects to hit the database every time a relationship is queried.  Since this is what most ORMs do anyway, it’s not too horrible.

I plan to have this issue resolved in time for the 0.9 release.  The biggest problem is figuring out how to flatten the multi-index structure into a single map.  Once I can do that, rewriting things for Memcached should be a snap.  (btw, if anyone wants to help out with patches in this area, you’re more than welcome!)

Databases Galore

One of the major focuses of this release was testing on different platforms.  This process uncovered an embarrassing number of bugs and glitches in some of the supposedly “supported” databases.  With the exception of Oracle, every bug I’ve been able to identify has been fixed.  So if you’ve tried ActiveObjects in the past and run into problems on non-MySQL platforms, now would be the time to give it another shot!

Speaking of Oracle, we’ve made some tremendous progress toward full support of this ornery database.  To be fair, I’m not the one responsible.  One of our community members has been tirelessly submitting patches and running tests.  We didn’t have time to get things fully sorted for this release (so don’t try AO 0.8 with Oracle unless you’re willing to risk server meltdown), but you can expect dramatic improvements in 0.9.  Once these fixes are in place, we should be able to safely claim that we support most of the database market (in terms of product adoption).

Final Thoughts

This really is an amazing release, well worth the download.  Most of the core API has remained the same, so things should be basically plug-n-play for existing applications.  The user-facing API is now in freeze and (unless some serious bug arises) will experience no changes between now and 1.0.  If you’ve been considering trying ActiveObjects for your project, now would be an excellent time.  I can’t promise no bugs, but if you point out my idiocy, I’ll certainly work to fix it!

Oh, as an aside, ActiveObjects is now in a Maven2 repository.  (thanks to some POM reworking by Nathan Hamblen)  To make use of this somewhat dubious feature, add the java.net Maven2 repository to your POM and then insert the following dependency:

<dependency>
    <groupId>net.java.dev.activeobjects</groupId>
    <artifactId>activeobjects</artifactId>
    <version>0.8</version>
</dependency>

After that, the magic of Maven will take over.  Of course, you’ll need to add the dependency for the appropriate database driver and (optionally) connection pool.  Those dependencies are left as an exercise to the reader.  Note, activeobjects-memcached isn’t in Maven yet, but it will be for the 0.9 release (either that or integrated into the core, I haven’t decided yet).

I certainly hope you enjoy this latest release.  As always, feel free to drop by the users list if you have any questions or (more likely) uncover any problems.

Should ORMs Insulate Developers from SQL?

25
Feb
2008

This is a question which is fundamental to any ORM design.  And really from a philosophical standpoint, how should ORMs deal with SQL?  Isn’t the whole point of the ORM to sit between the developer and the database as an all-encompassing, object oriented layer?

A long time ago in an office far, far away, a very smart cookie named Gavin King got to work on what would become the seminal reference implementation for object relational mapping frameworks the world over (or so Java developers would like to think).  This project was to be bundled with JBoss, possibly the most popular enterprise application server, and would support dozens of databases out of the box.  It was to offer heady benefits such as totally object-oriented database access, transparent multi-tier caching and a flexible transaction model.  At its core though, Hibernate was design to resolve a single problem: application developers hate SQL.

No really, it’s true!  Bread-and-butter application developers really dislike accessing data with SQL.  This has led to endless conflict (and bad jokes) between application developers and database administrators.  Often times the developer team would write a set of boilerplate lines in Java and then copy/paste these arbitrarily throughout their code, swapping in the relevant query as supplied by the DBA.  For obvious reasons, this would become very hard to maintain and just intensified the bad blood between developer and database.

If you think about it though, it’s a bit odd that this intense dislike would mutate from just hating the insanity of JDBC to hating JDBC, SQL and RDBMS in general.  SQL is a very nice, almost mathematical language which allows phenomenally powerful queries to be expressed simply and elegantly.  It abstracts developers from the headache of database-specific hashing APIs and algorithms which are almost filesystems in complexity.  The language was designed to make it as easy as possible to get data out of a relational database.  The fact that this effort backfired so utterly is a source of endless confusion to me.

But irregardless, we were talking about ORMs.  When it was first introduced, Hibernate held out the promise that developers would never again have to wade knee deep through a sea of half-set SQL.  Instead, developers would pass around POJOs (Plain Old Java Object(s)), modifying their values like any other Java bean and then handing these objects off to the data mapper, which would handle the details of persistence.  Furthermore, Hibernate promised that developers would never again have to worry about which databases support which non-standard SQL extensions.  Since developers would never have to work with SQL, anything database-specific could be handled within the persistence manager deep in the bowels of Hibernate itself.

This all seems lovely and wonderful, but there’s a catch: it doesn’t work so well in practice.  Now before you stone me, I’m not talking about Hibernate specifically now, but ORMs in general.  It turns out to be completely impossible to interact with a relational database solely through an object-oriented filter.  This is easily seen with a simple example:

SELECT * FROM people WHERE age > 21 GROUP BY lastName

How in the world are you going to represent that in an object model?  Sure, maybe you can provide a little abstraction for the query details, but it starts to get complex if you try to handle things like grouping non-declaratively.  The developers working on Hibernate quickly realized this problem and came up with an innovative solution: write their own query language!  After all, SQL is too confusing, so why not invent an entirely new query language with the “feel” of SQL (to keep the DBAs happy) but without all of the database-specific wrinkles?

This query language is now called “HQL”, and as the name implies, it’s really SQL, but not quite.  Here’s how the aforementioned example would look in HQL (disclaimer: I’m not a Hibernate expert, so I may have gotten the syntax wrong):

FROM Person WHERE :age > 21 GROUP BY :lastName

Remarkably similar, that.  Executing this query in a Hibernate persistence manager yields an ordered list of Person entities pre-populated with data from the query.  It seems to make a lot of sense, but there are a number of problems with this approach.  First, it requires Hibernate to literally have its own compiler to translate HQL queries into database-specific SQL.  Second, it hasn’t really solved the core problem that many developers have with SQL: it’s a declarative query language.  As you can see, HQL is really just SQL in disguise, so it really doesn’t eliminate SQL from your database access, just dresses it in a funny hat.

Other ORMs have appeared over the years, taking alternative approaches to the problem of object-relational mapping, but none of them quite eliminating the query language.  Even DSL-based ORMs like ActiveRecord fail to remove SQL entirely:

class Person < AR::Base; end
 
Person.find(:all, :conditions => 'age > 21', :group => 'lastName')

It’s sort of SQL-free, but you can still see bits and pieces of a query language around the edges.  In fact, what ActiveRecord is actually doing here is building a proper SQL query around the SQL fragments which are passed as parameters.  It’s a system which is ripe for SQL injection, but surprisingly leads to very few problems in real-world applications.  This is the approach which is also taken by ActiveObjects for its database query API.

So ORMs in and of themselves seem to have failed to entirely eliminate SQL from the picture, but what about other frameworks?  There are a few quite recent efforts which seem to have nearly succeeded in eliminating the direct use of SQL completely from application code.  Ambition is perhaps the best (and most clever) example of this, though others like scala-rel are catching up fast.  Ambition is designed from the ground up to interact naturally with ActiveRecord, so the two combined perhaps represent the first “true” ORM: one which does not require the developer at any point to deal with any SQL whatsoever.

But was it really worthwhile?  As clever as things like Ambition are, is it really that much easier than just writing queries in SQL?  As Nathan Hamblen so eloquently said (when referring to a totally different topic):

…is the end of the ORM rainbow.  You get there, throw yourself a party and realize that important things are broken.

A quote taken out of context perhaps, but I think it applies to the “cult of SQL genocide” with as much validity.  In the end, by denying yourself access to the powerful and well-understood mechanism that is SQL, you’re just crippling your own application and forcing yourself to write more code instead of less.

So what’s the “right” approach?  Is there a happy medium between ActiveRecord+Ambition and full-blown SQL on Rails?  I think so, and that is the approach I have been trying to implement with ActiveObjects.  As I’m sure you know, ActiveObjects takes a lot of its inspiration from ActiveRecord, so the syntax for querying the database is very similar:

EntityManager em = ...
em.find(Person.class, Query.select().where("age > 21").group("lastName"));
 
// ...or
em.find(Person.class, "name > 21");   // no grouping

You still have the full power of SQL available to you.  You can still write complex, nested boolean conditionals and funky subqueries, but there’s no longer any need to be burdened with the whole of SQL’s verbosity.  As with vanilla ActiveRecord, this code intends to be a bit of a hand-holder, shielding innocent application developers from the fierce world of RDBMS.

Is this the right way to go?  I’m honestly not sure.  I’ve met a lot of developers that would give their left eye to never have to look at another SQL statement again (for developers already missing a right eye, this isn’t much of a stretch).  On the other hand, there are purists like myself who revel in the freedom afforded by a powerful, declarative language.  It’s hard to say which path is better, but at the end of the day, it’s really the question itself that matters.  Giving application developers the choice to select whichever approach they feel is most appropriate, that is the solution.

ActiveObjects 0.7 Released

22
Dec
2007

Just in time for the Christmas holidays, I give you ActiveObjects version 0.7!  This release sports a whole slew of minor performance tweaks and bugfixes, providing better reliability.  Also, we’ve greatly increased the number and scope of the unit tests running against the core.  This gives us more confidence that the code is indeed as stable as we hope.

Actually, the big ticket item for 0.7 is the introduction of polymorphic relations.  This feature is fully tested and stable, so I don’t anticipate it introducing any issues in the coming days as we narrow our focus to 1.0.  However, no feature is so well tested as to be certainly bug free under all circumstances.  I look forward to fixing any problems you may encounter with the library!

A few minor feature additions:

  • Support for persisting enum values
  • One-to-one relations
  • EntityManager#flush(…) now also flushes the relations cache

Looking toward the road ahead, things are really starting to settle down a bit.  The main feature I’m looking to implement for 0.8 is extensible value caching, which should allow you to determine how and where the cached field values are stored.  The main use-case behind this is support for memcached, which has been requested a few times and has actually been on the agenda since 0.3.  With memcached driving the value cache, ActiveObjects should be almost perfectly scalable.

To that end, it’s also worth mentioning that I did some profiling (using the NetBeans Profiler) using a Wicket-based web application I’m developing on the side.  I’m happy to report that the overhead imposed by ActiveObjects is extremely minimal.  In each test, the bottleneck was in the PreparedStatement#execute method (in JDBC).  Since ActiveObjects generates very streamlined and natural queries, it seems that this is really the minimal execution time possible for such database access.  Extrapolating further from this data, and given that the JDBC exec time was avg 40ms, while the execution time in the ActiveObjects API was on the order of 1ms-5ms, we can safely say that ActiveObjects is less than 10% slower than using JDBC directly (compare that to the 50% overhead claimed by ActiveRecord).  This “estimate” doesn’t even take into account the many performance advantages offered by ORMs over hand-coded database access (such as relations caching, optimal query construction, etc).

Anyway, enough shameless boasting.  As Hibernate has often pointed out, ORM benchmarks are usually worse than useless.  The only benchmark which really matters is how well the ORM performs in your application.  Try it out, see what you think.

Table Inheritance with ActiveObjects

19
Nov
2007

The main obstacle in building an ORM is deciding how to map between a class hierarchy and a database table set.  While this may seem fairly clear cut in many situations, it’s unfortunately not so easy once you get into more complex issues like inheritance.

At a basic level, tables are classes.  It makes sense, right?  A class defines a structure which is instantiated and populated with data.  A table defines a structure into which data is inserted, one set per row.  Superficially, these two concepts sound more-or-less identical.  The differences creep in when you look at things like a class hierarchy.  Classes have the ability to inherit attributes from a superclass.  Thus, if class A inherits from class B, class A has everything that class B has (simplistically put). 

Unfortunately, database tables have no such capability.  You can’t define a table which has everything a “supertable” has.  Nor can you select data out of a “subtable” as if it were a supertable (polymorphism).  This lack of capability creates a disconnect between database structure and object-oriented class structure.

As with all of these “little differences” (between languages and databases), many solutions have been tried, none of them very successfully.  One of the most popular ways to solve the problem is to use separate tables for the supertable and subtable.  Then, whenever one SELECTs from the subtable, a JOIN is used to include the inherited row from the supertable in the result set.  In principle, it sounds right.  After all, this is how C++ handles inheritance.  However, in practice it becomes rather unwieldy.

To start with, JOINing every time you perform a simple SELECT is both inefficient and annoying.  Maintaining two separate rows is also a difficult problem to keep up with.  Inevitably, the data gets a bit out of sync and the whole thing falls apart.  Granted a good ORM will prevent this from happening in the first place, but ORMs are not the exclusive means for accessing database schemata.  Often times your schema will be in use not just by your application, but also by a web site, a demo utility and random DBAs who refuse to enter data in any way other than hand-written SQL.  In short, table inheritance using JOINs is clunky, unmaintainable and really messes you up down the line.

Another, more conservative way to map inheritance is inclining, where every subtable contains all of the fields which would be in a supertable.  Thus, if table A and B inherit from table C, table A and B are created with all of the fields that would have been in table C, and table C isn’t created at all.  Technically speaking, it’s not inheritance, just a slightly more centralized way to specify fields.  However, this technique is much more in line with how a database schema would normally work if designed by hand, and that’s what ORMs are supposed to simplify, right?

The ActiveObjects Approach

As you have have guessed from my comments, I really lean toward the inline strategy.  I think this works best in a practical environment and is far more maintainable down the line.  Thankfully, this strategy is considerably easier to implement than JOINing.  Syntax-wise, inheritance is used like this:

public interface Person extends Entity {
    public String getFirstName();
    public void setFirstName(String firstName);
 
    public String getLastName();
    public void setLastName(String lastName);
}
 
public interface Employee extends Person {
    public String getTitle();
    public void setTitle(String title);
 
    public short getHourlyRate();
    public void setHourlyRate(short rate);
 
    public Manager getManager();
    public void setManager(Manager manager);
}
 
public interface Manager extends Person {
    @OneToMany
    public Employee[] getPeons();
 
    public long getSalary();
    public void setSalary(long salary);
}

A fairly standard, object-oriented interface hierarchy, right?  Logically it makes sense.  This is how ActiveObjects would represent such a hierarchy in the database:

employees
id
firstName
lastName
title
hourlyRate
managerID

 

managers
id
firstName
lastName
title
salary

So basically inheritance in ActiveObjects is just a mechanism which allows the definition of common fields in a single place.  There’s no real polymorphism (that is to say, you can’t INSERT an employee where a person is required, since there is no “people” table).  The idea is: keep it simple stupid.  In fact, ActiveObjects would happily generate a table to correspond to Person if we asked it to, since as far as it’s concerned it’s just an entity like any other.

Of course, there are quite a few serious disadvantages to this approach.  For one thing, without polymorphism or actually centralizing the fields in a common table, inheritance is just an illusion.  From a database standpoint, the tables aren’t really related in any interesting way.  You’re still duplicating fields in the database (though not duplicating data), though since the duplication is all handled by the ORM, it’s not too much of an issue.

For me though, it all comes back to the decision I made to not make the schema over-complicated.  To ensure that no matter what the object hierarchy, it could be represented in the database (assuming it’s valid) without undue weirdness.  Keep the schema simple, make it easy to do stuff outside of the ORM.  The ORM should be a liberating too, not a constraining one.

I realize not everyone agrees with this particular style of table inheritance, so maybe at some point in the future ActiveObjects will allow configuration in this area.  But for the moment, the uncomplicated schema is the way to go.  :-)  Enjoy!

Thoughts on jPersist

15
Nov
2007

Disclaimer: For those of you who don’t know, my pet project is an ORM based on the active record pattern (ActiveObjects).  As such, my opinions are probably colored somewhat.  Take everything I say here with a grain of salt.

There seems to have been a recent resurgence of interest in Java implementations of the active record pattern in recent months.  Most traditional Java ORMs (like Hibernate/JPA) implement the data mapper pattern, as it is far easier to apply to a static language like Java.  Yet I can count a number of new (at least to me) ORM projects which attempt to fill this void.  One such project is jPersist.  From the project page:

jPersist is an extremely powerful object-relational persistence API that is based on the Active-Record pattern. jPersist is mapless and has no need for XML or annotation based mapping (all mapping is automatic and dynamic).

Sounds promising!  I’m always in favor of any framework which can reduce the boiler-plate configuration required, especially when the configuration would have been in a language as verbose as XML.  But irregardless of the method for configuration, I’m always interested in how alternative frameworks implement the active record pattern.  As they say, inspiration is one part perspiration and three parts plagiarism.

So I started to dig through the project page a bit, trying to find more info.  Unfortunately, the jPersist project page is a bit weird in how the whole thing is structured.  The page layout implies that jPersist is in fact a sub-project of some kind, which lead me to initially discount the “Documentation” link in the main nav bar.  Even after I found the documentation though, I was somewhat disappointed in its limited scope.  Effectively, the only documentation available is some basic javadoc and a “getting started” tutorial.  That’s alright though, I can work with that.  Code samples are more informative anyway, right?  I downloaded the full distribution (including javadoc and examples) and began to poke around.

The first thing I noticed upon opening the “DatabaseExample.java” file was the syntax: it’s very verbose.  Granted, most persistence APIs suffer from a less-than-DSL design, but I was still a bit taken aback at the volume of code required to accomplish a simple task.  For example, this is how you INSERT a new entity “Contact” with jPersist:

Database db = dbm.getDatabase();
db.saveObject(new Contact("alincoln", "mypasswd1", "Abraham", "Lincoln", 
        null, "alincoln@unitedstates.gov"));

This is assuming that you have defined the POJO Contact with a constructor taking all of the above arguments.  Obviously this could have been just as easily simplified into something more like this:

Contact c = new Contact();
c.setContactId("alincoln");
c.setPassword("mypasswd1");
c.setFirstName("Abraham");
c.setLastName("Lincoln");
c.setEmail("alincoln@unitedstates.gov");
 
Database db = dbm.getDatabase();
db.saveObject(c);

Still a bit verbose, but understandably so. I don’t know of any persistence API in Java that can accomplish the same thing more compactly, so I won’t hold it against jPersist. 

What really stands out at me in this example is that Contact isn’t actually a database peer, it’s a bean.  It’s just a regular, run-of-the-mill POJO created using a constructor upon which mutators are invoked.  This doesn’t really seem significant until you consider the claim from the project page (emphasis mine):

jPersist is an extremely powerful object-relational persistence API that is based on the Active-Record pattern.

Hmm, that’s odd, because it sure looks like data mapping to me.  By definition, the active record pattern requires the entities to directly peer to database rows or (more correctly) result-set rows.  You can’t just instantiate an active record entity, it must be created for you since it has to peer to the database somehow.  More importantly, to satisfy the active record pattern, entities must have the ability to persist themselves, at least from an API standpoint.  In this example, we have to haul around an instance of Database which we invoke separately to create, update, delete and query our entities.  This property is the hallmark of the data mapper pattern, which (as the name implies) involves a separate mapper which translates data from one form (entity beans) to another (database records).

Upon digging a bit further, I did manage to find “ProxyExample.java”.  The title itself seemed promising as any implementation of the active-record pattern in Java must utilize proxies at some level (JDK interface proxies or otherwise).  Digging into the source for the example, I discovered an interface Contacts extending DatabaseObject which was used further down in the following way:

Database db = dbm.getDatabase();
Contacts c = (Contacts) db.castDatabase(Contacts.class);
 
c.setResultSetConcurrency(ResultSet.CONCUR_UPDATABLE);
c.executeQuery("select * from contacts where 1 = 0");
 
c.moveToInsertRow();
c.setContactId("contactId" + System.currentTimeMillis());
c.setPassword("password");
c.setFirstName("First Name");
c.setLastName("Last Name");
c.setCompanyName("Company Name");
c.setEmail("email");
c.insertRow();

So it does seem that the active-record pattern is supported as a secondary mechanism for persistence (the documentation heavily emphasizes the data mapper style).  I do find it a bit odd though that we’re executing queries against an entity directly, cursoring around in result sets and still performing operations with a non-peered entity instance.  It’s also a bad sign that even having the documentation in front of me, as well as a pretty solid knowledge of database concepts, I’m still not entirely sure what the above code does on a semantic level.

Incidentally, if you look at the javadoc for DatabaseObject, it is basically functioning as a super-interface for any persistence class.  Database is the most notable implementation.  Thus, technically speaking we’re still not getting the active-record pattern in the above sample, we’re just being handed a data mapper which maps data from itself to the database.  You could make an argument that this satisfies the basic properties of active record, but I’m skeptical.

Along this line, I’d like to point out that the API of DatabaseObject (and by extension, Database) is heavily dependant on modification of its internal state.  For example, notice anything odd about the following snippet?

Database db = dbm.getDatabase();
db.queryObject(new Contact(), 
        "where :companyName = 'United States' order by :lastName");
 
Contact contact = null;
while (db.hasNext() && db.next() != null) {
    db.loadObject(contact = new Contact());
    System.out.println(contact);
}

Passing over the introduction of yet another framework-specific query language, notice the way the calls are structured?  Database itself is being used as an iterator.  So in a nutshell, you query the database using the queryObject(Object, String) method, which opens a result-set and saves it internally.  You then iterate over the database, loading the current object as you go.  If you want to be academic about this, what we have here is called an “internal iterator”.  As any compsci 201 student will tell you, internal iterators are bad news, both for concurrency and scalability.  Also, they tend to somewhat unintuitive APIs (iterating over a database?) and non-standard idioms.  In addition to all, this approach also imposes a hard limit on the number of queries which can be inspected at once against a given Database instance (one).  This leads to more odd idioms (like maintaining n Database instances for flexibility) and can introduce some bugs which would be very difficult to track down.

Moving on through the examples, a few more things jumped out at more, both positive and negative.  As I mentioned above, jPersist introduces its own SQL-derivative query language which allows querying for entities directly using field names (something supported by Hibernate using HQL but not by ActiveRecord or ActiveObjects).  Consider the following jPersist example:

Database db = dbm.getDatabase();
db.queryObject(new Contact(), 
        "where :companyName = 'United States' order by :lastName");

Compare to the corresponding ActiveObjects code:

EntityManager em = ...
Contact[] contacts = em.query(Contact.class, 
        Query.select().where("companyName = 'United States'").order("lastName"));

Hmm, which do you think is more readable? (hint: it ain’t ActiveObjects)

There are varying schools of thought on whether framework-specific query languages are a good idea or not.  Personally, I’m very opposed to them due to the added complexity and overhead they impose.  Why would I want to learn n different query languages rather than sticking with good old SQL?  On the flip side, I can see why such “spin-off” languages are nice when I look at examples like the above.  It’s really a matter of personal preference.

Another thing that’s really worth mentioning is the design decision made by jPersist not to avail itself of Java 5 syntax.  For example, if you want to use prepared statement parameters with a jPersist query, you must pass them in the following way:

db.queryObject(customer, "where :state = ? order by :lastName", 
        new Object[] {"arizona"});

A basic application of varargs would have simplified this API tremendously. Another example of the lack of Java 5 usage is in the active-record sample:

Contacts c = (Contacts) db.castDatabase(Contacts.class);

Notice the cast? Adding a type parameter to the castDatabase method would eliminate the cast entirely without bulking up the method call in any way.

The major advantage to not using Java 5 features is compatibility.  You can use jPersist on pre-Java 5 systems, possibly even back as far as Java 1.2 (not sure if it uses assertions or not).  Though, this advantage is of questionable value given the scarcity of such neolithic JVMs.

There’s more that’s worth mentioning, like the rather odd syntax for defining relations or the all-important schema generation, but this post is already pushing record sizes.  In brief: jPersist exhibits some interesting properties, and it certain provides a unique perspective on the field of database persistence, but I can’t say I’m particularly fond of the API.  Hopefully, the weaknesses I’ve enumerated will eventually be rectified, resulting in a really excellent library.