Achaius
Achaius

Reputation: 6124

Need best entity and query design to fetch object with multiple associations

I have an entity, which has multiple @ManyToOne associated objects. Currently I modelled all associated objects fetch type to LAZY.

Actually I am writing REST API to support various functionalities like

  1. Get an entity with @ManytoOne annotation resolving to just an id
  2. Get an entity with @ManytoOne annotation resolving to the entire object
  3. Get an entity with @ManytoOne annotation resolving to a partial object
  4. Fetch entities with @ManytoOne annotation resolving to just an id

My application was built using spring-boot jpa repository. Obviously the above variations in the REST API can be solved by writing named query for each API. If I do so, at one point there will be multiple named queries for each associated objects. But I am expecting a better approach to model and querying the entities.

Any suggestions are appreciated.

Upvotes: 1

Views: 249

Answers (2)

davidxxx
davidxxx

Reputation: 131456

In your case, queries which the structure is statically defined is really not suitable as you will indeed multiply the number of queries to write/modify/maintain.
JPA and Spring Data provide alternatives to create flexible queries and set the eager fetching dynamically :

  • JPA 2 - Criteria : Focused on dynamically build queries and eager fetching of the relationships.
    It is powerful but requires a important part of boiler plate code to create you criterias.

  • JPA 2.1 - Entity Graph : Focused on eager fetching of the relationships.
    This focus on eagerly fetched of the relationships.
    It is very simple and doesn't require boiler plate code.
    Just add the hint in the Query/Criteria you create.
    It can be used with JPQL queries or Criterias.

  • Spring Data - Specifications : Focused on dynamically build queries. It is a wrapper/enhancer of JPA Criteria with a Domain Driven Design vision. It is powerful but it is also verbose to setup.

  • Spring Data - Query by example : Focused on dynamically build queries. It is very simple, client friendly. It has some limitations and I don't think that the API be designed to set the fetch mode of the relationships of the queried entity.

For your requirement I would introduce two repository methods.
The first one would use the Criteria + Entity Graph to benefit from dynamically build queries and a simple way to set the eager fetching of the relationships for these cases :

Get an entity with @ManytoOne annotation resolving to just an id

Get an entity with @ManytoOne annotation resolving to the entire object

Get an entity with @ManytoOne annotation resolving to a partial object

And the second one method would use the Entity Graph + JPQL to only benefit from eager fetching for this one :

Fetch entities with @ManytoOne annotation resolving to just an id

With Criteria + Entity Graph, you could get a single method that does everything but having a complex method that does a lot of things is not necessarily the best choice.

Upvotes: 1

Mickael
Mickael

Reputation: 4558

From my understanding, you should use Query by Example

The Query by Example API consists of three parts:

  • Probe: The actual example of a domain object with populated fields.
  • ExampleMatcher: The ExampleMatcher carries details on how to match particular fields. It can be reused across multiple Examples.
  • Example: An Example consists of the probe and the ExampleMatcher. It is used to create the query.

Query by Example is well suited for several use cases:

  • Querying your data store with a set of static or dynamic constraints.
  • Frequent refactoring of the domain objects without worrying about breaking existing queries.
  • Working independently from the underlying data store API.

Query by Example also has several limitations:

  • No support for nested or grouped property constraints, such as firstname = ?0 or (firstname = ?1 and lastname = ?2).
  • Only supports starts/contains/ends/regex matching for strings and exact matching for other property types.

Upvotes: 1

Related Questions