I noticed an abstraction leak that I think merits discussion WRT dynamic finder methods that employ the dynamic finder method keyword "Like". Based on my trials, if I define a method "findByXxx", where "xxx" is a string property of an entity, it looks like SD JPA ultimately uses the SQL "=" operator. If I define "findByXxxLike", it uses SQL's "LIKE" syntax. In both of these cases, the argument given is passed verbatim down through the SQL. In the case of "=", that seems appropriate. In the case of "LIKE", however, I see some issues.
JPQL's LIKE syntax allows for defining the ESCAPE character (see the JPA spec section 4.6.10, "Like Expressions"):
In the current SD JPA implementation, it looks like the caller of the dynamic finder method
string_expression [NOT] LIKE pattern_value [ESCAPE escape_character]
The string_expression must have a string value. The pattern_value is a string literal or a string-valued
input parameter in which an underscore (_) stands for any single character, a percent (%) character
stands for any sequence of characters (including the empty sequence), and all other characters stand for
themselves. The optional escape_character is a single-character string literal or a character-valued
input parameter (i.e., char or Character) and is used to escape the special meaning of the underscore
and percent characters in pattern_value.
Should SD abstract the user from these details or is it a necessary abstraction leak that SD JPA users must use JPQL wildcards and must RTFM for the correct escape character to use, if any?
- must know which wildcards to use and
- has no way of specifying the escape character.
To solve issue #1 above, perhaps new dynamic finder keywords are in order here, similar to "Like" but instead are "StartingWith", "EndingWith" or "Containing":
For issue #2 above, I suppose the current "Like" dynamic finder keyword should treat the given string as a technology-specific expression, and, in the case of SD JPA, should accept "_" & "%" with an escape character of "\".
// for JPA, uses "%" + value
List<Foo> findByXxxStartingWith(String value);
// for JPA, uses value + "%"
List<Foo> findByXxxEndingWith(String value);
// for JPA, uses "%" + value + "%"
List<Foo> findByXxxContaining(String value);