JDO Typesafe Refactorable Queries

One of the primary drawbacks with current JDO queries is that they are string-based, so you are hardcoding field names etc. When you refactor a (model) class, the field names are left unchanged, so the query no longer works. Some efforts have been made to simplify this process by providing a form of type-safe query (called “criteria” queries by some, but the name is misleading since all queries define criteria) – see JPA2 Criteria queries, and also QueryDSL. Of the current offerings the QueryDSL fluent API approach is considered by many to be the most elegant.

JDO needs such a type-safe refactorable query API. However it is important that this does not go down the track followed by JPA Criteria queries (IMHO) since it leads to excessive code just to generate a query, hence the fluent approach make more sense. What we are proposing would be something similar to the following (taken from QueryDSL, but adapted to use more JDOQL-like syntax)

QCustomer customer = QCustomer.customer;
Query q = pm.newTypesafeQuery(customer);
Customer bob = q.filter(customer.firstName.eq("Bob"))
.unique(true).execute();

where the QCustomer class is generated automatically (during compilation via an annotation processor, or optionally via a separate process when not using JDO annotations).

The idea is to provide support for all JDOQL syntax via this API, yet provide type-safe handling and refactorability, introducing this in the DataNucleus AccessPlatform 2.2 timeframe, and finally to standardise something similar into JDO 3.1. Your ideas/comments are welcome.

Advertisements
This entry was posted in JDO, JDOQL. Bookmark the permalink.

8 Responses to JDO Typesafe Refactorable Queries

  1. Just for reference. The main drawbacks of the JPA 2 Criteria approach are
    * static metamodel instead of dynamic
    * no fluent operation creation, Builder usage instead
    * no single query object for population

    And another thing which should be corrected in the post. With a non-generic Query instance the return value needs to cast to Customer or otherwise Query needs to take a type parameter. In Querydsl queries the projection is defined in the end, so there is no need for a type parameter for the query.

    Like

  2. andy says:

    Re: the Query taking a type param … yes of course, which is what I had in my post, just that Blogger didn't show the angle brackets and interpreted them as some HTML tag :-(, now corrected, thx.

    Like

  3. I also sketched some variations of your query example here

    Just to show the possible directions the Query interface could take.

    Like

  4. Without Sun RFEs like
    http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=5043025
    and
    http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6915224

    I suppose an APT or postcompilation tool would be ok. If enough people vote for RFEs like this, at least the probability that they'll implement goes up. Better, if someone had time to implement and submit a patch to Sun, we'd all benefit. I'd do it if I had the time… 😦

    Like

  5. andy says:

    Even with those RFE's I don't see how the query implementation would know that the information it is given by the Java runtime for “a.b.c” (i.e the “c” field of the “b” object) is actually “a.b.c” … i.e contain knowledge of the parent object of each “field”.

    Also bearing in mind that JDK1.7 is taking forever, we cannot wait for such a change IMHO.

    Like

  6. Marin says:

    I have to compare an integer property to another in a typesafe query.
    For example: QAcademicYear.startYear.gteq(…)
    However startYear is an ObjectExpression which does not have any gteq method like ComparableExpression does.
    I’m wondering if there’s any way I can get a ComparableExpression for QAcademicYear.startYear ??

    Like

  7. datanucleus says:

    All “normal” date/time types come across as DateExpression, TimeExpression, DateTimeExpression not ObjectExpression. You don’t define your field type

    Like

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s