How to fetch EntityGraph dynamically in Spring Boot
you can do this in the repository:
interface ProductRepository extends Repository<Product, Long> {
Product findOneById(Long id);
@EntityGraph(attributePaths = {"tags"})
Product findOneWithTagsById(Long id);
}
and create a service method as Robert Niestroj proposed.
You can choose EntityGraph at runtime, by using Spring Data JPA EntityGraph.
Setup quite simple:
- Add:
implementation 'com.cosium.spring.data:spring-data-jpa-entity-graph:2.0.7'
to build.gradle - Add:
@EnableJpaRepositories(repositoryFactoryBeanClass = EntityGraphJpaRepositoryFactoryBean.class)
bellow@SpringBootApplication
Now, you can choose the best EntityGraph at runtime. Example (this is the example from Spring Data JPA EntityGraph):
// This will apply 'Product.brand' named EntityGraph to findByLabel
productRepository.findByLabel("foo", EntityGraphs.named("Product.brand"));
// This will apply 'Product.supplier' named EntityGraph to findByLabel
productRepository.findByLabel("foo", EntityGraphs.named("Product.supplier"));
// This will apply 'supplier' attribute paths EntityGraph (don't need to define named EntityGraph) to findByLabel
productRepository.findByLabel("foo", EntityGraphUtils.fromAttributePaths("supplier"));
Please read the document for more information.
You can add an Entity graph as bellow, make sure the entity product class has a relation with the tag class.
@EntityGraph(attributePaths = {
"tags"
})
@Query( value = "select product from product)
List<Product> findAllProduct();
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);
}
}