Skip to content

Latest commit

 

History

History
167 lines (143 loc) · 5.29 KB

File metadata and controls

167 lines (143 loc) · 5.29 KB

Quick start

  1. In addition to spring-data-jpa, add the library dependency :

    <dependency>
        <groupId>com.cosium.spring.data</groupId>
        <artifactId>spring-data-jpa-entity-graph</artifactId>
        <version>${spring-data-jpa-entity-graph.version}</version>
    </dependency>
  2. In your Spring configuration, set the repository factory bean class to EntityGraphJpaRepositoryFactoryBean :

    @Configuration
    @EnableJpaRepositories(repositoryFactoryBeanClass = EntityGraphJpaRepositoryFactoryBean.class)
    public class DataRepositoryConfiguration {
        //...
    }
  3. Make sure your repositories extend the Spring Data standard ones or the library provided repositories:

  • EntityGraphJpaRepository which is equivalent to standard JpaRepository
  • EntityGraphJpaSpecificationExecutor which is equivalent to standard JpaSpecificationExecutor
  • EntityGraphQuerydslPredicateExecutor which is equivalent to standard QuerydslPredicateExecutor
  • EntityGraphCrudRepository which is equivalent to standard CrudRepository
  • EntityGraphPagingAndSortingRepository which is equivalent to standard PagingAndSortingRepository
  • EntityGraphQueryByExampleExecutor which is equivalent to standard QueryByExampleExecutor

Basic Usage

Let's consider the following entities and repository :

@Entity
public class Brand {
    @Id
    private long id = 0;
    private String name;
    //...
}
@NamedEntityGraphs(value = {
    @NamedEntityGraph(name = "Product.brand", attributeNodes = {
        @NamedAttributeNode("brand")
    })
})
@Entity
public class Product {
    @Id
    private long id = 0;
    private String name;
    @ManyToOne(fetch = FetchType.LAZY)
    private Brand brand;
    //...
}	
public interface ProductRepository extends EntityGraphJpaRepository<Product, Long> {
    List<Product> findByName(String name, EntityGraph entityGraph);
}

You can pass the entity graph to the findByName method :

// This will apply 'Product.brand' named EntityGraph to findByName
productRepository.findByName("MyProduct", EntityGraphs.named("Product.brand"));

Or to the findOne method :

// This will apply 'Product.brand' named EntityGraph to findOne
productRepository.findById(1L, EntityGraphs.named("Product.brand"));

Or any method you like.

You can also pass a dynamically built EntityGraph by using DynamicEntityGraph, it's also accessible through a helper method:

productRepository.findById(1L, EntityGraphUtils.fromAttributePaths("brand", "maker"));

This is similar to Spring's ad-hoc attribute paths, and equivalent to writing this in your repository's interface:

@EntityGraph(attributePaths = { "brand", "maker" })
Product findById(Long id);

Type safe EntityGraph

Composing entity graphs by hand can be tedious and error prone. Wouldn't it be great to benefit from autocompletion and strong type checking while composing your entity graph?

spring-data-jpa-entity-graph-generator has you covered.

This annotation processor makes use of the JPA metamodel informations (part of JPA specification) generated by the tool of your choice (e.g. hibernate-jpamodelgen) to generate EntityGraph composers allowing you to safely and easily compose EntityGraph at runtime.

You first need to add a JPA metamodel information generator. hibernate-jpamodelgen is great and should be compatible with any JPA ORM:

<dependency>
    <groupId>org.hibernate</groupId>
    <artifactId>hibernate-jpamodelgen</artifactId>
    <version>${hibernate.version}</version>
    <scope>provided</scope>
</dependency>

Then add the entity graph generator annotation processor dependency:

<dependency>
  <groupId>com.cosium.spring.data</groupId>
  <artifactId>spring-data-jpa-entity-graph-generator</artifactId>
  <version>${spring-data-jpa-entity-graph.version}</version>
  <scope>provided</scope>
</dependency>

After compiling your project, you should find XEntityGraph classes where X is the name of your Entity. Thanks to them, you will be able to build entity graphs like this:

// Let's build entity graph "product(brand, category, maker(country))"
EntityGraph entityGraph = ProductEntityGraph
                    .____()
                    .brand()
                    .____
                    .category()
                    .____
                    .maker()
                    .country()
                    .____
                    .____();

productRepository.findById(1L, entityGraph);

Default EntityGraph

For an Entity, you can define its default EntityGraph.
An Entity default EntityGraph will be used each time the Entity repository method is called without EntityGraph.

A default EntityGraph name must end with .default.

@NamedEntityGraphs(value = {
    @NamedEntityGraph(name = "Product.default", attributeNodes = {
        @NamedAttributeNode("brand")
    })
})
@Entity
public class Product {
    @Id
    private long id = 0;
    private String name;
    @ManyToOne(fetch = FetchType.LAZY)
    private Brand brand;
    //...
}	
// This call will make use of "Product.default" EntityGraph.
productRepository.findById(1L);