Skip to content
Print

An Easier Java ORM

18
Jul
2007

There is no doubt that Hibernate is the dominant ORM for Java applications. There are Hibernate conferences and Hibernate user groups. It even has its own shelf at Barnes and Nobel. However, I have always found it suffering from a fatal flaw: it’s incredibly complex. Even accomplishing the simplest of functionality requires hundreds of lines of code, reams of boiler-plate POJO definitions, and a fair share of XML. Granted, it’s probably simpler and more scalable than using JDBC in its raw form, but I still think it makes things harder than they have to be.

This has been a common theme throughout most ORMs in any language. Even various Python ORMs, touted for simplicity and power, still remained burdened with either cryptic syntaxes, or mountains of boiler-plate. This general failing is probably the single most important factor which has contributed to the success of Ruby on Rails.

Rails is nothing without its flagship component, ActiveRecord. AR provides an incredibly simple and powerful database wrapper layer which makes working with almost any schema simple and intuitive. Granted, migrations are a bit weird and it’s performance is far from satisfactory, but the fact remains that it’s much easier, quicker (and thus cheaper, at least in the short term) to develop a database-reliant application using ActiveRecord than it is to build the same application on top of Hibernate or iBatis. This has been carried to such an extreme that developers have taken to using ActiveRecord on top of JDBC through JRuby just to handle the database layer of their Java application. Clearly a better solution is required.

Much of ActiveRecord’s power is drawn from the fact that very little code is required to interact with the database. For example, extracting data from a hypothetical people table in a database is as simple as:

class Person < ActiveRecord::Base
end
 
puts Person.find(1).first_name   # roughly == SELECT first_name FROM people WHERE id = 1

Obviously, the first_name method doesn’t exist in the Person class. This code is using a feature of Ruby which allows for methods to be defined at runtime (or rather, not defined and just handled). It should be apparent how much this could simplify database access, and how unfortunately inapplicable it is to Java.

Fortunately, the principles of ActiveRecord are not entirely irrelevant. The Java reflection API contains a little-known feature called interface proxies. It allows code to define a dynamic implementation of a given interface which handles method invocations in a single, dynamic location. It’s not quite dynamic method definitions, but it is dynamic method handling and it eliminates a lot of boiler-plate.

So what good does this do us? Enter ActiveObjects!

ActiveObjects is a Java ORM based on the concept of interface proxies. The whole idea behind it is that you shouldn’t have to write any more code than absolutely necessary. In fact, ActiveObjects was designed from the ground up to be dead-easy to use. Here’s a rough approximation of the previous ActiveRecord example, translated into Java using the ActiveObjects ORM:

public interface Person extends Entity {
    public String getFirstName();
    public void setFirstName(String firstName);
}
 
EntityManager em = new EntityManager(jdbcURI, username, password);
 
Person p = em.get(1);
System.out.println(p.getFirstName());    // executes "SELECT firstName FROM person WHERE id = 1"

Isn’t that refreshingly simple? With the exception of placing the appropriate JDBC driver in the classpath, that’s all there is to using ActiveObjects. AO automatically detects the database type from the JDBC URI and loads the appropriate driver. If you have placed a pooling library on the classpath, it will be used to pool the database connections. You’ll notice the Person implementation is created by the EntityManager instance corresponding to the (presumably existing) database row, and the SQL is automatically generated and executed, typing the result and returning it from the method. AO even uses PreparedStatement(s) for maximum performance (currently unsupported by ActiveRecord). And if we were to call the setFirstName(String) method, an SQL UPDATE statement would be automatically executed based on the data specified.

Of course, simple CRUD operations do not an ORM make. For one thing, it’d be really nice to be able to automatically generate database-specific DDL statements, ala Hibernate and ActiveRecord. Coolly enough, ActiveObjects allows for this too:

System.out.println(Generator.generate("../classes", "jdbc:mysql://localhost/db", "test.package.Person"));

This would output:

CREATE TABLE person (
    ID INTEGER AUTO_INCREMENT,
    firstName VARCHAR(45),
    PRIMARY KEY(ID)
);

With a different JDBC URI, the DDL would be different. ActiveObjects completely insulates the developer from any database inconsistencies. In fact, the only steps needed to switch to a different database are to place the appropriate driver on the classpath, and to change the URI.

To round up our little tour of ActiveObjects, it’s worth looking at relations a bit. In ActiveRecord, relations are specified using the has_many and belongs_to methods. Hibernate uses annotations/custom javadoc syntax to accomplish roughly the same thing. In ActiveObjects, things are nice and clean:

public interface Person extends Entity {
    public String getFirstName();
    public void setFirstName(String firstName);
 
    public House getHouse();
    public void setHouse(House house);
}
 
public interface House extends Entity {
    public String getAddress();
    public void setAddress(String address);
 
    @OneToMany
    public Person[] getPeople();
}

With just the above entity definitions, calls can be made to instances of Person, passing the House instance to store. Likewise, House#getPeople() can be called, which will return an array of all Person instances associated with that House. Obviously, the Java instance itself isn’t being stored in the database, but rather the houseID INTEGER value is persisted, through the restriction of the appropriate foreign key.

It almost seems magical when you first start using it. :-) I’ve written two test applications (not downloadable, but included within the ActiveObjects SVN) which illustrate the framework’s potential more fully. Also, I’ve been using ActiveObjects as the basis for a reasonably complex Wicket application deployed in the “real world”, and I must say it’s performed beautifully.

Now here comes a moment of bad news: it’s not fully documented yet. Since it’s only on its 0.3 release, I’ve been more interested in squashing bugs and adding features than writing javadoc, though I assure you it is on my agenda. There are a few brief (and somewhat dated) examples on the website, as well as partial javadoc for the EntityManager class. Thankfully, the framework itself is remarkably intuitive and very easy to pick up.

There’re so many more cool features I would love to have shown here, but unfortunately all bloggers have sworn in blood that they will not extend their posts beyond 1500 words. If you are interested, I’ll write a follow-up post going into further detail about the framework (including the more performant SaveableEntity super-interface, which does not execute an UPDATE on every setter call).

Do yourself a favor and take a look at the API and examples. Once you get used to the simplicity of Entity interfaces and non-configuration of database connections, you’ll never look back.

https://activeobjects.dev.java.net

Comments

  1. Interesting stuff Daniel! Could you provide more details on how that looked in your Wicket based project? Would a integration project (ActiveObjects Wicket) be an idea?

    Eelco Hillenius Wednesday, July 18, 2007 at 3:19 am
  2. How about things like first level cache (for efficiency and to detect cycles)? And do you force users to use interfaces or can they use normal classes? And why didn’t you choose for a Entity annotation rather than an interface?

    I guess I’ll have to check out the sources myself first, huh? :)

    Eelco Hillenius Wednesday, July 18, 2007 at 3:34 am
  3. I would really appreciate additional info for SaveableEntity and for some further features that are inside. Lacking ActiveRecord style ORM on JAVA keep us on Rails. This can direct us back to JAVA. Syntaxt of ActiveObject is amazingly easy to adopt and flexible. What are the planned features you are thinking about. Can you imagine some implementation of migrations for instance?

    Thanks a lot for this project
    David

    David Marko Wednesday, July 18, 2007 at 4:31 am
  4. Pretty Neat stuff… I understand that this is just in 0.3 version, but still, i am not very comfortable with the interface approach, primarily because it is far easier to generate getters and setters from instance variables than to write both getters and setters by hand…

    I guess, there should be a better solution for that.

    -Ganesh

    Ganeshji Marwaha Wednesday, July 18, 2007 at 11:49 am
  5. @Eelco

    Yeah, I’m planning on writing an article in the near future talking about how I’m using AO within Wicket. Most of my custom code AO-Wicket relates to the fact that Entities aren’t serializable (since they’re just cached database peers) so special care needs to be taken with models and listviews. It’s fairly straightforward stuff, but I’d love to get the integration closer where possible. This is an area where I have interest, but no clear idea as to what form an integration project would take. Maybe I should look at the Wicket-Hibernate project… :-)

    Re: interfaces vs classes: Unfortunately, Java interface proxies only work with interfaces, and not with implemented classes. AO does allow for property change listeners (Java Bean Spec). More usefully, it also allows for custom implementations of methods (ala ActiveRecord method overrides), but I’ll freely admit that the syntax is perhaps a little unintuitive.

    I thought about using an entity annotation to just tag entity interfaces rather than extending a predefined interface. But by extending Entity, all entities can inherit methods like getID(), setID(int), getTableName(), addPropertyChangeListener(PropertyChangeListener), etc… rather than having to define these methods in every entity interface. SaveableEntity is a better example of this, since it defines a save() method to execute any pending UPDATEs.

    @Ganeshji

    Yeah, I’ll freely admit that the major downside to ActiveObjects is it still has a lot of boiler-plate (though still less than POJO-based ORMs). Fortunately, writing getter and setter signatures by hand isn’t too terrible. I’d love to cut down on this boiler-plate still further, but unfortunately Java’s inherent limitations prevent us from going as far as an ActiveRecord-style method_missing.

    Daniel Spiewak Wednesday, July 18, 2007 at 11:52 am
  6. Where would you code a business rule like “every person must have a house” or “every person must have a name which may not be blank”?

    Your api is a way of persisting a set of data transfer objects.

    Hibernate allow one to persist a set of domain model objects that contain the system business rules – which is a hudge difference.

    richard Wednesday, July 18, 2007 at 3:17 pm
  7. You don’t have to limit yourself using normal normal JDK proxies though. There are plenty of project that use e.g. cglib to create dynamic proxies using byte code manipulation. Amongst others Hibernate and wicket-ioc.

    Eelco Hillenius Wednesday, July 18, 2007 at 3:36 pm
  8. Maybe Databinder (http://databinder.net/site/show/overview) is something to look at when thinking about an integration project. I’m not sure either. But as you’re trying to cut the ammount of code you need to write, it probably should provide some very convenient models and transaction utilities.

    Eelco Hillenius Wednesday, July 18, 2007 at 3:37 pm
  9. Sorry for spamming, but another thing to look at – if you’re interested – is the phonebook example (http://wicket-stuff.svn.sourceforge.net/svnroot/wicket-stuff/trunk/wicket-phonebook). That’s an example project that shows how you *could* use Hibernate, Shades or iBatis with Wicket. And maybe ActiveObjects sometime as well :)

    Drop me a line if you want write access to wicket-stuff.

    Eelco Hillenius Wednesday, July 18, 2007 at 3:43 pm
  10. @richard

    Well, you’ve got two choices for the example you gave. You can define the database schema attributes to not allow nulls in the houseID field:

    public interface Person extends Entity {
    // …

    @NotNull
    public House getHouse();
    @NotNull
    public void setHouse(House house);
    }

    Or for a more complex rule, you could use AO implementations, which are definitely weird, but quite powerful. I’ll make sure I cover them in a future post.

    @Eelco

    I’ll take a look at those wicket sources. Since I’m working on a project using Wicket and ActiveObjects, it’d obviously be nice to make the integration as tight as possible.

    I’ll have to look at cglib and similar. I briefly considered byte-code manipulation when designing the framework, but that always required weird hacks like custom classloaders etc… While I don’t have a problem writing framework internals which do weird stuff, I don’t want the API to be too bizarre. :-)

    Daniel Spiewak Wednesday, July 18, 2007 at 3:52 pm
  11. Have you taken a look at BeanKeeper before?

    http://www.netmind.hu/persistence/

    It’s another persistence library with a similar philosophy – zero configuration, no boilerplate code, no administration, etc. I’ve used it a bit in the past, and it’s really quite cool how it magically stores and loads objects without any ugly ORM code or configuration. If you are familiar with it, what would you say are main advantages of ActiveObjects over BeanKeeper?

    Daniel Thursday, July 19, 2007 at 12:41 pm
  12. @Daniel

    No, I wasn’t familiar with it actually. It does seem interesting though. My three problems with it just from reading bits of the tutorial:

    * Still requires a lot of boiler-plate code (it’s POJO based)
    * Has it’s own query syntax (HQL is a big reason I avoid Hibernate)
    * Seems to be List based for relations, rather than the more intuitive (and performant) array based

    The problem with POJO-based frameworks, beyond the added boiler-plate, is that everything must be eagerly loaded. Basically, you turn every entity retrieval call into a SELECT * Hibernate can get around this with bytecode manipulation, but personally I’m a little leery of letting random frameworks peer into my class internals.

    In ActiveObjects, every value is lazy-loaded and cached. So you use a minimal amount of memory for each entity.

    Daniel Spiewak Thursday, July 19, 2007 at 1:26 pm
  13. Thanks for the response. Regarding your comments:

    *** Still requires a lot of boiler-plate code (it’s POJO based)

    I may be misunderstanding something here. In BeanKeeper your class definition would be:

    public class Person {
    private String firstName;
    public String getFirstName() { return firstName; }
    public void setFirstName(String firstName) { this.firstName = firstName; }
    }

    In ActiveObjects your class (interface) definition would be:

    public interface Person extends Entity {
    public String getFirstName();
    public void setFirstName(String firstName);
    }

    So, by “boilerplate code”, are you referring to the implementation of the getters and setters? I suppose it is a bit of extra code, but at the same time, being able to use POJOs like this gains you a lot of flexibility:

    - You can easily add custom code to your getters and setters
    - Works well to persist existing/legacy classes
    - External users of your entity classes do not have know or care about the persistence manager, they just create and use POJOs like any other object

    I suppose the above may just be general benefits of doing things the POJO way. Anyway, for my particular project, the above points were quite important – I’m sure there are cases where they are not as important (e.g. starting a new project from scratch).

    *** Has it’s own query syntax (HQL is a big reason I avoid Hibernate)

    Doesn’t AO have its own query syntax too? BeanKeeper queries don’t seem all that different from AO queries to me, for example:

    manager.find(Person.class, “name LIKE ? OR age > ?”, “Joe”, 9); // AO
    store.find(“find person where name LIKE ‘Joe’ OR age > 9″); // BK

    *** Seems to be List based for relations, rather than the more intuitive (and performant) array based

    BeanKeeper’s lazy lists are actually the primary reason I used the library for a previous project – you can execute queries that return huge lists with very low memory usage. By using the List interface instead of arrays, BeanKeeper can page objects into memory only when they are actually accessed. This sort of feature is really useful for reporting, where you may be dealing with queries that return hundreds of thousands of objects.

    BTW, what is the reason that arrays are more intuitive? Doesn’t everyone these days use Collections instead of arrays (unless you’re doing some low-level stuff)? Regarding performance, it seems unlikely that there would be any noticeable difference between using arrays and Lists for an ORM library.

    *** In ActiveObjects, every value is lazy-loaded and cached. So you use a minimal amount of memory for each entity.

    Agreed, this is a benefit of using an interface and not a POJO. On the other hand, if you do need to access all the data in an object, it is more efficient to do a single SELECT * than to execute many smaller queries. The memory use of a single object does not typically cause too many problems – it’s normally only when you have thousands of objects in memory at the same time, and the BeanKeeper lazy lists address this issue quite well.

    I’m definitely looking forward to trying out ActiveObjects soon. I have a few small BeanKeeper test programs, so it’ll be interesting to re-implement them with ActiveObjects and compare the code and results.

    Daniel Thursday, July 19, 2007 at 4:29 pm
  14. Well, I’ll grant you that boiler-plate POJO vs Proxy is probably about equal. I suppose at some minimal level, the compiler still has to be satisfied. And as pointed out earlier, the POJO approach has the major advantage in that all getters and setters can be generated from fields.

    AO actually doesn’t have it’s own query syntax. It’s just using PreparedStatement fragments. For the example you gave, the fragment of “query text” is actually concatenated directly into an SQL query, like so: “SELECT id FROM person WHERE ${query_text}”, and then executed with the specified parameters. I didn’t look, does BK actually use PreparedStatements? And if so, how effectively? This is a really important issue, especially for databases like Derby or Oracle which rely heavily on PS and have lousy performance without them.

    Point taken on the SELECT * vs lazy load. Actually, it’s possible in AO to do this sort of thing (I added the functionality like two weeks ago, so like most things it isn’t documented yet). The code would look something like this:

    manager.find(Person.class, Query.select(“*”).where(“name LIKE ? OR age > ?”, “Joe”, 9));

    Query is just a preparedstatement builder class which allows things like: Query.select().where(“name = ?”, “Bill”).limit(5).order(“name”) => “SELECT id FROM ${table_name} WHERE name = ? ORDER BY name LIMIT 5″. The idea behind it is that it mimics the ActiveRecord find() syntax a bit, through the filter that Java doesn’t have symbols like Ruby.

    Daniel Spiewak Thursday, July 19, 2007 at 5:37 pm
  15. Here comes another project to check

    ynw Tuesday, August 28, 2007 at 3:36 am
  16. I , nice work.
    I have a doubt.
    how you can identifi a Enum java type into SQL type?

    Cristian Gary Thursday, December 20, 2007 at 7:09 pm
  17. @Cristian

    Pre-0.7 (the soon-to-be-released version in the SVN) enum storage wasn’t possible using the vanilla distribution. The extensible type system of course allowed for such a mapping to be trivially implemented (and that is how it is now done in the core), but previously it was not available “out of the box”.

    After much wrestling with the pros and cons, the decision was made to use the ordinal value of the enum, rather than the String name. This obviously makes it slightly less readable on the database, but it allows for trivial name-refactorings without breaking database integrity. Thus, the corresponding type for enum is INTEGER.

    Perhaps down the road AO will support database-specific type implementations like MySQL’s ENUM, but at the moment this too must be done outside of the core (possible, but not implemented).

    Daniel Spiewak Thursday, December 20, 2007 at 10:17 pm

Post a Comment

Comments are automatically formatted. Markup are either stripped or will cause large blocks of text to be eaten, depending on the phase of the moon. Code snippets should be wrapped in <pre>...</pre> tags. Indentation within pre tags will be preserved, and most instances of "<" and ">" will work without a problem.

Please note that first-time commenters are moderated, so don't panic if your comment doesn't appear immediately.

*
*