As a ...
I need to be able to ...
specify JDQL expressions or fragments of JDQL in annotations.
Which enables me to ...
reduce the cognitive dissonance in moving between @Find and @Query.
Additional information
So in thinking through:
- the nature of the
@By annotation,
- the potential for us to grow a whole zoo of similar animals in future (
@Like, @IgnoreCase, @In, etc), and
- also about my unexpected happiness with how well
@OrderBy("name") works, and unhappiness with how ugly @OrderBy(vale="name",descending=true,ignoreCase=true) looks.
I came to the realization that there's a general approach that makes @Find much more flexible, reduces the conceptual gap between @Find and @Query, solves the problem with @OrderBy, and makes the trip to the zoo unnecessary.
[Don't get scared. I'm not proposing to do any of this today, I'm just trying to understand what the future might look like.]
The idea is to have a smaller set of annotations which accept fragments of JDQL. So, for example:
@Find
@OrderBy("lower(title) desc")
@OrderBy("isbn")
List<Book> booksByTitle(Type type, @Where("title like :pattern") String pattern);
which would be assembled to:
@Query("where title like :pattern and type = :type order by lower(title) desc, isbn")
List<Book> booksByTitle(Type type, String pattern);
You might even be able subsume @Where into @By, since it's pretty easy to distinguish a scalar expression with no parameters from a conditional expression with a parameter. And you might allow @OrderBy to accept a list. So:
@Find
@OrderBy("lower(title) desc, isbn")
List<Book> booksByTitle(Type type, @By("title like :pattern") String pattern);
Now, one might look at this particular example, and think "but the @Query version is shorter and perhaps even more readable", and that's true because this is a sort-of "extreme" case in the sense that I have three annotations and only two parameters. But if I had four parameters and just one or two annotations, it would look more attractive.
But that's anyway not the point. The point is to reduce the pressure to add lots of special-purpose annotations, and save the developer from getting into the sort of edit war where they find themselves switching back and forth between @Find and @Query.
To reiterate: @Where("title like :pattern") is more verbose than @Like. But it covers many more cases and is somehow, at least to my way of thinking, a much more elegant approach.
Note that the content of these annotations can still be checked at compile time. JDQL has a very a simple expression language that's easy to parse in an annotation processor.
So we would have:
@By accepting scalar_expression,
@OrderBy accepting orderby_item or perhaps a whole list of them,
@Where accepting conditional_expression except for logical operators, and
- possibly
@Select accepting select_list or perhaps just a single select item.
By side effect, @By("id(this)") becomes the much more elegant way to write @By(ID).
Everything here looks backward-compatible with what we have today! That said, we could consider adopting this approach for @OrderBy in this release, if we have time. But it's definitely not critical.
As a ...
I need to be able to ...
specify JDQL expressions or fragments of JDQL in annotations.
Which enables me to ...
reduce the cognitive dissonance in moving between
@Findand@Query.Additional information
So in thinking through:
@Byannotation,@Like,@IgnoreCase,@In, etc), and@OrderBy("name")works, and unhappiness with how ugly@OrderBy(vale="name",descending=true,ignoreCase=true)looks.I came to the realization that there's a general approach that makes
@Findmuch more flexible, reduces the conceptual gap between@Findand@Query, solves the problem with@OrderBy, and makes the trip to the zoo unnecessary.[Don't get scared. I'm not proposing to do any of this today, I'm just trying to understand what the future might look like.]
The idea is to have a smaller set of annotations which accept fragments of JDQL. So, for example:
which would be assembled to:
You might even be able subsume
@Whereinto@By, since it's pretty easy to distinguish a scalar expression with no parameters from a conditional expression with a parameter. And you might allow@OrderByto accept a list. So:Now, one might look at this particular example, and think "but the
@Queryversion is shorter and perhaps even more readable", and that's true because this is a sort-of "extreme" case in the sense that I have three annotations and only two parameters. But if I had four parameters and just one or two annotations, it would look more attractive.But that's anyway not the point. The point is to reduce the pressure to add lots of special-purpose annotations, and save the developer from getting into the sort of edit war where they find themselves switching back and forth between
@Findand@Query.To reiterate:
@Where("title like :pattern")is more verbose than@Like. But it covers many more cases and is somehow, at least to my way of thinking, a much more elegant approach.Note that the content of these annotations can still be checked at compile time. JDQL has a very a simple expression language that's easy to parse in an annotation processor.
So we would have:
@Byacceptingscalar_expression,@OrderByacceptingorderby_itemor perhaps a whole list of them,@Whereacceptingconditional_expressionexcept for logical operators, and@Selectacceptingselect_listor perhaps just a single select item.By side effect,
@By("id(this)")becomes the much more elegant way to write@By(ID).Everything here looks backward-compatible with what we have today! That said, we could consider adopting this approach for
@OrderByin this release, if we have time. But it's definitely not critical.