• GraphQL Java


    映射数据

    GraphQL将数据映射到相应类型上

    GraphQL的核心思想,就是声明一种类型schema,并将它映射到运行时产生的数据上。

    设计这些类型时,要充分考虑到类型与相应数据的映射方式。

    例如,假设我们有如下类型:

        type Query {
            products(match : String) : [Product]   # a list of products
        }
    
        type Product {
            id : ID
            name : String
            description : String
            cost : Float
            tax : Float
        }
    

    可以在这个简单的schema上执行一些简单的查询:

        query ProductQuery {
            products(match : "Paper*")
            {
                id, name, cost, tax
            }
        }
    

    然后,在Java代码中需要为Query.products字段绑定DataFetcher,以通过传入的参数获取product列表。

    假设我们有三个下游服务: 一个获取产品信息,一个获取产品成本信息,一个获取产品税信息。

    GraphQL - Java会在运行时调用dataFetcher获取对象的数据,并将其映射为schema中定义的类型。

    在这个场景下,主要问题是:如何将三种不同来源的数据汇集为一个单一的类型数据。

    一种方式是,在cost和tax字段上添加dataFetcher,首先获取产品列表,然后分别在每个产品的cost、tax上执行dataFetcher。这种方式会比较容易维护,但也很容易产生N+1性能问题。
    我们也可以在Query.products字段的dataFetcher上同时做三个下游信息的服务调用,然后创建一个统一数据展示视图。如下所示:

            DataFetcher productsDataFetcher = new DataFetcher() {
                @Override
                public Object get(DataFetchingEnvironment env) {
                    String matchArg = env.getArgument("match");
    
                    List<ProductInfo> productInfo = getMatchingProducts(matchArg);
    
                    List<ProductCostInfo> productCostInfo = getProductCosts(productInfo);
    
                    List<ProductTaxInfo> productTaxInfo = getProductTax(productInfo);
    
                    return mapDataTogether(productInfo, productCostInfo, productTaxInfo);
                }
            };
    

    在上面的代码中,我们有三种不同类型的数据,需要整合为一个GraphQL可以查询的数据(在本例中,可以供GraphQL查询id、name、cost、tax字段)。

    有两种方式可以创建这种映射。一种是,通过使用List结构。另一种是,首先定义一个ProductDTO类,然后返回List类型数据。

    使用Map结构的代码如下:

        private List<Map> mapDataTogetherViaMap(List<ProductInfo> productInfo, List<ProductCostInfo> productCostInfo, List<ProductTaxInfo> productTaxInfo) {
            List<Map> unifiedView = new ArrayList<>();
            for (int i = 0; i < productInfo.size(); i++) {
                ProductInfo info = productInfo.get(i);
                ProductCostInfo cost = productCostInfo.get(i);
                ProductTaxInfo tax = productTaxInfo.get(i);
    
                Map<String, Object> objectMap = new HashMap<>();
                objectMap.put("id", info.getId());
                objectMap.put("name", info.getName());
                objectMap.put("description", info.getDescription());
                objectMap.put("cost", cost.getCost());
                objectMap.put("tax", tax.getTax());
    
                unifiedView.add(objectMap);
            }
            return unifiedView;
        }
    

    使用DTO结构的代码如下:

        class ProductDTO {
            private final String id;
            private final String name;
            private final String description;
            private final Float cost;
            private final Float tax;
    
            public ProductDTO(String id, String name, String description, Float cost, Float tax) {
                this.id = id;
                this.name = name;
                this.description = description;
                this.cost = cost;
                this.tax = tax;
            }
    
            public String getId() {
                return id;
            }
    
            public String getName() {
                return name;
            }
    
            public String getDescription() {
                return description;
            }
    
            public Float getCost() {
                return cost;
            }
    
            public Float getTax() {
                return tax;
            }
        }
    
        private List<ProductDTO> mapDataTogetherViaDTO(List<ProductInfo> productInfo, List<ProductCostInfo> productCostInfo, List<ProductTaxInfo> productTaxInfo) {
            List<ProductDTO> unifiedView = new ArrayList<>();
            for (int i = 0; i < productInfo.size(); i++) {
                ProductInfo info = productInfo.get(i);
                ProductCostInfo cost = productCostInfo.get(i);
                ProductTaxInfo tax = productTaxInfo.get(i);
    
                ProductDTO productDTO = new ProductDTO(
                        info.getId(),
                        info.getName(),
                        info.getDescription(),
                        cost.getCost(),
                        tax.getTax()
                );
                unifiedView.add(productDTO);
            }
            return unifiedView;
        }
    

    GraphQL - Java在运行时会直接在对象列表或Map列表上进行查询,获取id、name、cost、tax字段的值。

    GraphQL - Java中默认的dataFetcher是PropertyDataFetcher,它可以直接在Map或POJO数据上执行查询。

    对于列表中的每个对象或Map,例如:id字段,在Map中通过同名key("id")或pojo中的getter方法(getId()方法)查找数据,然后返回。

    通过在dataFetcher上创建“统一的视图”,实现运行时数据 -> GraphQL类型Schema之间的映射。

  • 相关阅读:
    5.1.5 JunkMail Filter
    POJ1067 取石子游戏 跪跪跪,很好的博弈论
    USACO Section 3.2 Magic Squares (msquare)
    5.1.1 A Bug's Life
    USACO Section 3.3 Riding The Fences (fence)
    USACO Section 3.1 Stamps (stamps)
    5.2.7 Entropy
    USACO Section 3.1 AgriNet (agrinet)
    5.1.8 How Many Answers Are Wrong
    4.3.6 N皇后问题
  • 原文地址:https://www.cnblogs.com/pku-liuqiang/p/11527737.html
Copyright © 2020-2023  润新知