Ashwani K Ashwani K - 13 days ago 6
Java Question

How to fetch EntityGraph dynamically in Spring Boot

I am developing an application using Spring Boot using JPA.
In the application I am exposing rest API. I do not want to use Spring data rest as I want to have full control on the data.

I am not able to figure out how to use EntityGraph dynamically.

Suppose I have following model taken from here

@Entity
class Product {

@ManyToMany
Set<Tag> tags;

// other properties omitted
}

interface ProductRepository extends Repository<Customer, Long> {

@EntityGraph(attributePaths = {"tags"})
Product findOneById(Long id);
}


I have following rest link to access Product
http://localhost:8090/product/1

It returns me product with id 1

Questions:


  1. Will it by default fetch tags as we have mentioned @EntityGraph?
    If yes then can this be configured on demand? Say, if in the query
    string I have include=tags, then only I want to fetch product with
    its tags.



I found this article but not sure how this can be of help.

Answer

The definition of the EntityGraph in the Spring Data JPA Repository is static. If you want to have it dynamic you need to do this programatically like in the page you linked to:

EntityGraph<Product> graph = this.em.createEntityGraph(Product.class);
graph.addAttributeNodes("tags"); //here you can add or not the tags

Map<String, Object> hints = new HashMap<String, Object>();
hints.put("javax.persistence.loadgraph", graph);

this.em.find(Product.class, orderId, hints);

Also you can define the method with the EntityGraph in your JPA Repository.

interface ProductRepository extends Repository<Product, Long> {

@EntityGraph(attributePaths = {"tags"})
@Query("SELECT p FROM Product p WHERE p.id=:id")
Product findOneByIdWithEntityGraphTags(@Param("id") Long id);
}

And then have a method in your service which uses this method with the EntityGraph or the built in findOne(T id) without the EntityGraph:

Product findOneById(Long id, boolean withTags){
  if(withTags){
    return productRepository.findOneByIdWithEntityGraphTags(id);
  } else {
    return productRepository.findOne(id);
  }
}