Saturday, December 08, 2007

Using SQL on Java Collections

On the project I work on, we have an in memory model of some particularly useful data (a POJO model as it were). A situation that regularly occurs with this useful data is that various groups want the data sliced and diced in various manners.

Each time a request comes in we have to write a new method that iterates through our collection, sometimes making a new comparator and then return a subset of the objects. I've often wished for a way to just query those objects without having to put them in a database or writing my own domain specific language. Anyone who tells you domain specific languages (DSLs) are a good idea is trying to sell you a DSL framework.

Hibernate's HQL looks pretty sweet, and if there was a way I could just toss objects into a second level cache without a database and do HQL on the cache, that would solve my problem. But I can't.

Java 6's jmap tool has OQL support, but it seems to be a custom OQL implementation for jmap. I did some digging around and the closest thing I could find that would OQL on a collections of objects was db4o which is effectively commercial for my purposes.

Then I ran across JoSQL. It's exactly what I'm looking for. From some poking around, it's fairly decent performing. A large amount of time is spent parsing queries so preparsed queries are in order. Plus, the query objects are not thread safe, so those preparsed queries will need to be in an object pool. Not a big deal.

Lastly, its syntax for handling objects with lists is a bit awkward. As an example, instead of "SELECT * FROM recipes WHERE ingredients.name = 'butter'", you would need to write "SELECT * FROM recipes WHERE (SELECT * FROM ingredients WHERE name='butter')". These sub-selects continue to nest as long as your model has collections of collections.

It's nice since most decent developers know enough SQL to get by, and it's a lot faster to write a query to say "show the top five most popular recipes with butter in them posted in the past 30 days" in SQL than it is in Java. JoSQL supports returning queries as a TableModel too, which could potentially solve some "I want to see my data in fifteen different configurations" issues I'm dealing with too.

Overall, I was quite impressed! If I get time to add it into my project, I'll post an update.

6 comments:

Anonymous said...

JXPath?

Jose Noheda said...

Hibernate has an @Filter annotation that serves the purpose (for persistent collections, of course)

gdefacci said...

I think you are missing quaere (http://quaere.codehaus.org/) which is a sort of linq for java. I think linq is next generation data quering tool.
Quaere is not so different from JoSql. The main point is that using quaere you express your queries using java syntax (which is better, in my opinion), instead of using sql like syntax.
Give quaere a look. It's a very very nice project.

idcmp said...

@gdefacci

You're right, I hadn't heard of Quaere; it looks like it's still pretty new. Quaere's syntax seems very jMock-like (I'm not sure what the correct term is). Also, it's not as simple as JoSQL. In Quaere I would write:

largePopulations = from("city"). in(cities). where(gt("city.getPopulation()", 10000000)). select("city.getName()");


But in JoSQL I would write:

SELECT name FROM cities WHERE population > 10000000

One last thing I hadn't mentioned in my post; the ability to dynamically create queries at runtime with JoSQL is a big win for me too. With Quaere I would need to route them through Groovy to do something similar.

I bet for a lot of people Quaere would suit their needs, but for me JoSQL seems to have stronger parity. Thanks for the tip!

idcmp said...

@anonymous

I ran across JXPath in my searches, but to be honest, I simply don't know XPath well enough to do the kind of queries I'd easily do in a SQL-like language. Also, not everyone on my team is versed in XPath, but all of them have at least some basic familiarity with SQL.

gdefacci said...

@idcmp

i agree with you: every tools, its use. I feel very confortable with java syntax so my preference is easily explained..
There's another project on codehaous.org wchich i think you may find intersting http://xircles.codehaus.org/projects/jequel

I just checkout the svn, so i cant give you many infos.