【问题标题】:How to fetch EntityGraph dynamically in Spring Boot如何在 Spring Boot 中动态获取 EntityGraph
【发布时间】:2016-03-01 15:36:32
【问题描述】:

我正在使用 JPA 使用 Spring Boot 开发应用程序。 在应用程序中,我公开了一个休息 API。我不想使用 Spring data rest,因为我想完全控制数据。

我无法弄清楚如何动态使用 EntityGraph。

假设我有以下模型取自here

   @Entity
class Product {

  @ManyToMany
  Set<Tag> tags;

  // other properties omitted
}

interface ProductRepository extends Repository<Customer, Long> {

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

我有以下链接可以访问产品 http://localhost:8090/product/1

它返回给我一个 id 为 1 的产品

问题:

  1. 默认情况下会像我们提到的@EntityGraph 那样获取标签吗? 如果是,那么可以按需配置吗?说,如果在查询中 字符串我有 include=tags,那么我只想获取产品 它的标签。

我找到了this 文章,但不确定这有什么帮助。

【问题讨论】:

标签: java spring jpa spring-data spring-data-jpa


【解决方案1】:

Spring Data JPA Repository 中EntityGraph 的定义是静态的。如果您想让它动态化,您需要像在链接到的页面中那样以编程方式执行此操作:

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);

您还可以在 JPA 存储库中使用 EntityGraph 定义方法。

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);
}

然后在您的服务中有一个方法,该方法将此方法与 EntityGraph 或内置的 findOne(T id) 一起使用,而不使用 EntityGraph:

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

【讨论】:

    【解决方案2】:

    您可以在运行时选择 EntityGraph,使用 Spring Data JPA EntityGraph
    设置很简单:

    • 添加:implementation 'com.cosium.spring.data:spring-data-jpa-entity-graph:2.0.7' 到 build.gradle
    • 加:@EnableJpaRepositories(repositoryFactoryBeanClass = EntityGraphJpaRepositoryFactoryBean.class)下面@SpringBootApplication

    现在,您可以在运行时选择最佳 EntityGraph。示例(这是来自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"));
    

    请阅读文档以获取更多信息。

    【讨论】:

      【解决方案3】:

      您可以在存储库中执行此操作:

      interface ProductRepository extends Repository<Product, Long> {
      
          Product findOneById(Long id);
      
          @EntityGraph(attributePaths = {"tags"})
          Product findOneWithTagsById(Long id);
      }
      

      并按照 Robert Niestroj 的建议创建服务方法。

      【讨论】:

        【解决方案4】:

        您可以添加一个实体图如下,确保实体产品类与标签类有关系。

        @EntityGraph(attributePaths = {
                "tags"
            })
        @Query( value = "select product from product)
        List<Product> findAllProduct();
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2014-10-03
          • 1970-01-01
          • 2019-12-01
          • 2021-03-15
          • 1970-01-01
          • 1970-01-01
          • 2019-03-21
          • 2014-05-17
          相关资源
          最近更新 更多