GraphQL DataLoader для двунаправленных сущностей Hibernate и проблема N+1

Я получил эти двунаправленные объекты:

      @Getter
@Setter
@Entity
@Table(name = "category")
public class CategoryEntity {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "id")
    private Integer id;
    @Column(name = "name")
    private String name;
    @Column(name = "parent")
    private Integer parent;
    @Column(name = "product_id")
    @ElementCollection
    private List<Integer> productIds;
    
}


@Getter
@Setter
@Entity
@Table(name = "product")
public class ProductEntity {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "id")
    private Integer id;
    @Column(name = "productId")
    private String productId;
    @Column(name = "description")
    private String description;
    @Column(name = "item_id")
    @ElementCollection
    private List<Integer> itemIds;
    @Column(name = "category_id")
    private Integer categoryId;

}

И я получил эту схему:

      extend type Query {
    getProduct(id: Int!) : ProductResponse
    getProducts : [ProductResponse]
    getLimitedProducts(limit: Int) : [ProductResponse]
}

type ProductResponse {
    id: Int!,
    productId: String!,
    description: String!,
    category: CategoryResponse,
    items: [ItemResponse]
}

type CategoryResponse {
    id: Int,
    name: String,
    parent: Int,
    products: [Int]
}

Чтобы избежать проблемы N + 1, я реализовал DataLoader для разрешения категории для каждого продукта:

        private DataLoader<Integer, Category> createCategoryDataLoader() {
    MappedBatchLoader<Integer, Category> categoryMappedBatchLoader =
        categoryIds -> CompletableFuture.supplyAsync(
            () -> categoryRepository.findAllById(categoryIds).stream()
                .map(c -> conversionService.convert(c, Category.class))
                .filter(Objects::nonNull)
                .collect(Collectors.toMap(Category::getId, Function.identity())));

    return DataLoaderFactory.newMappedDataLoader(categoryMappedBatchLoader);
  }

Теперь, когда я выбираю товары без двунаправленных полей, все выглядит нормально:

      {
  getLimitedProducts(limit: 15) {
    category {
      id
    }
  }
}

Hibernate: select productent0_.id as id1_3_, productent0_.category_id as category2_3_, productent0_.description as descript3_3_, productent0_.product_id as product_4_3_ from product productent0_ limit ?
Hibernate: select count(productent0_.id) as col_0_0_ from product productent0_
Hibernate: select categoryen0_.id as id1_0_, categoryen0_.name as name2_0_, categoryen0_.parent as parent3_0_ from category categoryen0_ where categoryen0_.id in (? , ? , ? , ? , ?)

Но когда я добавляю [Product] для получения категории, я сталкиваюсь с проблемой N+1:

      {
  getLimitedProducts(limit: 15) {
    category {
      id,
      products
    }
  }
}

Hibernate: select productent0_.id as id1_3_, productent0_.category_id as category2_3_, productent0_.description as descript3_3_, productent0_.product_id as product_4_3_ from product productent0_ limit ?
Hibernate: select count(productent0_.id) as col_0_0_ from product productent0_
Hibernate: select categoryen0_.id as id1_0_, categoryen0_.name as name2_0_, categoryen0_.parent as parent3_0_ from category categoryen0_ where categoryen0_.id in (? , ? , ? , ? , ?)
Hibernate: select productids0_.category_entity_id as category1_1_0_, productids0_.product_id as product_2_1_0_ from category_entity_product_ids productids0_ where productids0_.category_entity_id=?
Hibernate: select productids0_.category_entity_id as category1_1_0_, productids0_.product_id as product_2_1_0_ from category_entity_product_ids productids0_ where productids0_.category_entity_id=?
Hibernate: select productids0_.category_entity_id as category1_1_0_, productids0_.product_id as product_2_1_0_ from category_entity_product_ids productids0_ where productids0_.category_entity_id=?
Hibernate: select productids0_.category_entity_id as category1_1_0_, productids0_.product_id as product_2_1_0_ from category_entity_product_ids productids0_ where productids0_.category_entity_id=?
Hibernate: select productids0_.category_entity_id as category1_1_0_, productids0_.product_id as product_2_1_0_ from category_entity_product_ids productids0_ where productids0_.category_entity_id=?

Как можно решить этот вопрос?

0 ответов

Другие вопросы по тегам