8

Is there a way to define a Spring Data Specification (returning a JPA predicate) whose sole purpose is to perform eager fetching?

I have an entity which defines various relationships using lazy loading, but there are several queries where I want to return the entire entity representation including all related collections, but the criteria of these queries may vary. I've seen a few posts (e.g. on the spring forum) that discuss the potential introduction of fetch groups, which would likely be the ideal solution; however, since this is not yet part of the JPA spec, Spring Data does not provide support for it.

I'm looking for a reusable way to perform eager fetching on a variety of dynamic queries.

For example, I've considered developing a reusable Specification whose sole purpose is to perform the eager loading, and which could be combined with other specifications, e.g:

private static Specification<MyEntity> eager() {

    return new Specification<MyEntity>() {

        @Override
        public Predicate toPredicate(Root<MyEntity> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
            for (PluralAttribute<? super MyEntity, ?, ?> fetch : root.getModel().getPluralAttributes()) {
                root.fetch(fetch, JoinType.LEFT);
            }
            query.distinct(true);
            return null;
        }

    };
}

The goal of this specification is to reuse it in various queries, e.g:

repository.findAll(where(eager()).and(otherCriteria).or(otherCriteria));

However, the eager fetching specification is not a true predicate, so it returns null, and would cause obvious problems (i.e. NullPointerExceptions) when chained with other predicates.

(Note that this predicate alone does work as expected; i.e. the following query will properly fetch: repository.findAll(eager());).

Is there an appropriate non-null Predicate that can be returned from the "eager" specification, or are there any other reusable approaches for triggering eager fetches using Spring Data JPA specifications (without having to tack the eager load onto another specification)?

shelley
  • 7,206
  • 4
  • 36
  • 63
  • I am getting following exception when using your approach: "query specified join fetching, but the owner of the fetched association was not present in the select list". – svlada Apr 21 '15 at 19:00
  • alternatively, is there an approach like this that would work to make all relationships lazy? – chrismarx Nov 05 '15 at 19:20

1 Answers1

6

We have improved the handling of null Specifications and Predicates in the course of fixing DATAJPA-300. You might wanna give the 1.4 snapshots a try and see how this affects your scenario.

Oliver Drotbohm
  • 80,157
  • 18
  • 225
  • 211