A couple weeks ago, I pinged our fearless leader. I needed some direction before taking on a couple tasks. One of these tasks I was thinking about, which seemed tiny at the time, I joked “for THAT one, perhaps I should write a parser?”
He rolled his eyes. “We don’t need a parser.”
Two weeks later…
Spring Data JPA has a handy feature where you can dynamically feed it ORDER BY clauses with simple strings, e.g. Sort.by(“firstname”). This nicely gets turned into a JPA Criteria Expression object.
In the simplest of cases, this is an entity type’s property name. However, we have always offered this escape hatch where you can feed it ANYTHING. For example, you could feed it LENGTH(firstname) as your criteria to apply an ORDER BY to a query, where you order things not by the row’s firstname but instead by the length of the row’s firstname. Basically, anything that your JPA provider supports.
In my pre-op analysis, I uncovered a seemingly endless supply of hacks and workarounds on StackOverflow.com. I was beginning to think that this feature NEVER worked!
Quite naturally, as a test-bitten script junky, my first step was to write a test case. LENGTH(firstname) seemed like the textbook scenario that perfectly captured the situation while being easy to reason over.
Right there, in the middle, you can see LENGTH(firstname) nestled in the midst of JpaSort.unsafe(). To be clear, this query essentially says “find all objects and order them not by their firstname, but instead by the length of their firstname. (This query also has a paging argument, which I won’t delve into).
With this tasty string value at my finger tips, I cracked open JPA’s CriteriaBuilder interface and began scouring it, looking for the place where you feed it a string like that and get handed back an Expression.