Reputation: 1679
I have some Spring entities and repositories with a chain of associations:
Root -> Foo -> Bar -> Qux -> ...
Something like this:
class Root {
private String rootData;
@OneToOne
private Foo foo;
}
class Foo {
private String fooData;
@OneToOne
private Bar bar;
}
class Bar {
private String barData;
@OneToOne
private Qux qux;
}
class Qux {
private String quxData;
@OneToOne
private GoesOn goesOn;
}
There are hundreds of thousands of Root objects and all associations are Lazy.
I need to create a report listing all Root objects with the follogwing data:
If I try to populate the report navigating through the associations there will be N more queries to the database for each Root object.
Is there a way to retrieve all data with a single query using joins, without changing the associations to eager?
Upvotes: 0
Views: 1209
Reputation: 1679
@Antoniossss answer solved it for me .
After some more testing and based on this article I managed to do it with a simpler solution, without the NamedEntityGraph. I created a function inside my RootRepository interface with the following:
@EntityGraph(attributePaths = {"foo.bar.qux"})
List<Root> findAllEagerJoin(Specification<Root> spec);
Asking for a attribute at the end of the association chain forced the join of all tables.
Upvotes: 1
Reputation: 410
You can use HQL or JOINS SELECT t1, t2 FROM Table1 t1, Table2 t2 WHERE t1.x = t2.x
Upvotes: 0
Reputation: 32535
You can use entity graph to specify which properties should be fetched directly (in eagar way)
You annotate one of your entities with
@NamedEntityGraph(
name = "report-eg",
attributeNodes = {
@NamedAttributeNode("foo"),
@NamedAttributeNode(value = "bar", subgraph = "bar-eg"),
},
subgraphs = {
@NamedSubgraph(
name = "bar-eg",
attributeNodes = {
@NamedAttributeNode("qux")
}
)
}
)
And then you use it within fetch
EntityGraph entityGraph = entityManager.getEntityGraph("report-eg");
Map<String, Object> properties = new HashMap<>();
properties.put("javax.persistence.loadgraph", entityGraph);
Post post = entityManager.find(Foo.class, id, properties);
Obviously, you will have to probably adjust some that graph for your needs, but it shouws you the way to go.
Alternatively, you could use Criteria API. It allows directly to specify which relations should be fetched
(in contrast to join)
Upvotes: 2