Currently I have been using following Spring JPA Repository base custom query and it works fine,
@Query("SELECT usr FROM User usr WHERE usr.configurable = TRUE "
+ "AND (" +
"lower(usr.name) like lower(:filterText) OR lower(usr.userType.classType.displayName) like lower(:filterText) OR lower(usr.userType.model) like lower(:filterText)"
+ ")"
+ "")
public List<User> findByFilterText(@Param("filterText") String filterText, Sort sort);
I need to modify this query when filter text going to be a comma separated value. But as following manner it will be a dynamic query and how can I execute it.
Dynamic query I need to build,
String sql = "SELECT usr FROM User usr WHERE usr.configurable = TRUE";
for(String word : filterText.split(",")) {
sql += " AND (lower(usr.name) like lower(:" + word + ") OR lower(usr.userType.classType.displayName) like lower(:" + word + ") OR lower(usr.userType.model) like lower(:" + word + "))";
}
Per JB Nizet and the spring-data documentation, you should use a custom interface + repository implementation.
Create an interface with the method:
Create an implementation:
Extend the new interface in your existing Repository interface:
Finally, call the method somewhere else:
Query implementation
Your method of producing the
sql
variable, namely by concatenating some strings into the query is bad. Do not do this.The
word
which you are concatenating must be a valid JPQL identifier, namely a:
followed by a java identifier start, optionally followed by some java identifier part. This means that if your CSV containsfoo bar,baz
, you will attempt to usefoo bar
as an identifier and you'll get an exception.You can instead use
CriteriaBuilder
to construct the query in a safe way:I've been looking for the solution myself : The naming of the "Custom" repository interface and implentation is very strict (as said there How to add custom method to Spring Data JPA)
So, to be clear, the whole code : (But @beerbajay was right)
The custom method interface
The custom method implementation
The "original" repository
You can now use the "original" repository with the new custom methods
Spring Data JPA has a way to create Custom and Dynamic queries with "Specifications": Spring Data - Specifications
First, your interface which extends
JPARepository
orCRUDRepository
should also implementJpaSpecificationExecutor<...>
and that's all you need. Your repository now has a new methodfindAll
which accepts aSpecification<...>
object, and your can use the method Beerbajay used to create Criteria Queries by overriding the methodtoPredicate(...)
and there you are free to build (almost) any query you want like so:This solves the problem of Spring Data trying to parse the methods you added in the custom interface (because there is no custom interface)