marcellorvalle
marcellorvalle

Reputation: 1679

Retrieving data from multiple table joins using Spring and Hibernate

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

Answers (3)

marcellorvalle
marcellorvalle

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

Rakesh Singh Balhara
Rakesh Singh Balhara

Reputation: 410

You can use HQL or JOINS SELECT t1, t2 FROM Table1 t1, Table2 t2 WHERE t1.x = t2.x

Upvotes: 0

Antoniossss
Antoniossss

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

Related Questions