As you note:
I can do it with HQL with no problem, but then I would have to write
several similar queries depending on which data I need in a specific
context.
I assume then that the ultimate solution would look something like the below where one query method can be defined but to which we can pass both dynamic criteria (be these either direct or nested properties of an Entity) and a dynamic fetch plan defining those EntityGraphs to be activated:
public interface CompanyRepository{
List<Review> findAll(Criteria criteria, FetchPlan fetchPlan);
}
The Spring Data project can actually get us part of the way there but not, at the current time,
all of the way (although there is some discussion around regarding the missing part: see further below).
What it does do at the moment is the first part:
public interface CompanyRepository{
List<Review> findAll(Criteria criteria);
}
either by means of the Specification pattern (http://docs.spring.io/spring-data/jpa/docs/1.8.0.M1/reference/html/#specifications) or,
more simply, by using QueryDSL's fluent API as an alternative to the JPA Criteria API.
Using the QueryDSL approach then we can create a Repository definition like this:
public interface ReviewRepository extends CrudRepository<Review, Long>, QueryDslPredicateExecutor<Review>{
}
Now, and without creating an implementation (created by the framework) or writing any more code we can call it as below,
with any combination of attributes:
Review review = respository.findOne();
Iterable<Review> reviews = respository.findAll(QReview.review.created.eq(someDate));
Iterable<Review> reviews = respository.findAll(QReview.review.created.eq(someDate).and(QReview.review.creator.forename.eq("Jim"));
Iterable<Review> reviews = respository.findAll(QReview.review.created.eq(someDate).and(QReview.review.creator.forename.eq("Jim").and(QReview.review.company.name.eq("Amazon"));
etc....
where QReview is a Query Type auto generated by the QueryDSL library and giving you strongly typed queries and the findOne(Predicate predicate) and findAll(Precicate predicate) methods are inherited from:
http://docs.spring.io/spring-data/commons/docs/current/api/org/springframework/data/querydsl/QueryDslPredicateExecutor.html
This then gives you a lot for very little (zero) code other than creating some interface definitions but would still require an additional
(sub-optimal in terms of DB interactions) mechanism for handling the lazy loading i.e. one of the mechanisms highlighted in your other recent
question and which led on to this one.
I do not see however why Spring Data could not be updated to handle the dynamic specification of EntityGraphs and there has indeed been
some discussion around this so it may be in the pipeline:
http://forum.spring.io/forum/spring-projects/data/108202-custom-fetch-groups-with-spring-data-jpa-possible
so might be worth raising a JIRA to see if this something they are planning or asking
https://stackoverflow.com/users/18122/oliver-gierke
directly.
Some support has been added to Spring Data for the new JPA 2.1 EntityGraph functionalityb however I do not see that it can be made to work with a generic query method like we want here:
http://docs.spring.io/spring-data/jpa/docs/1.8.0.M1/reference/html/#jpa.entity-graph