Most serious projects I've seen land in one of two places: lazy + proliferation of nearly-identical queries that differ only in what they fetch, or they give up on mapping relationships altogether and treat their relational DB like a document DB. The others either have these performance issues, or don't yet know that they have them.
`EntityGraph` looked like it was finally going to fix this. Call-site fetch control, no more one-size-fits-all fetch strategies — great idea. But the API they gave us sucks. If you've ever tried to use it, you know what I mean. In fact, I've yet to see any actual uses of it in real production apps.
So I built the API I wish the spec had given us. Since we can't change the spec, this was the next best thing — it extends and mimics the `EntityManager` API, but makes fetch control a first-class concern rather than an afterthought bolted on via `EntityGraph`. You express fetch paths as generated QueryDSL path varargs — compile-time checked, refactor-safe, and composable:
entityFinder.find(Person.class, id,
QPerson.person.organization().country(),
QPerson.person.role());
It also works with JPA metamodel attributes, but that API is clunkier because the metamodel spec never gave us composable paths like QueryDSL did. Person person = entityFinder.find(Person.class, id,
FetchPaths.of(Person_.organization, Organization_.country),
FetchPaths.of(Person_.role));
The library builds and merges the `EntityGraph` for you at runtime. Same idea works for inline JPQL and named queries via a fluent `TypedQuery`-compatible API.https://github.com/alterioncorp/jpa-fetch
I've been using this concept in various forms in production since EntityGraphs were first introduced. Finally decided to clean it up and put it out there. Maybe others find it useful.