GraphQL Java - Data Mapping

映射數據

GraphQL將數據映射到相應類型上

GraphQL的核心思想,就是聲明一種類型schema,並將它映射到運行時產生的數據上。java

設計這些類型時,要充分考慮到類型與相應數據的映射方式。ide

例如,假設咱們有以下類型:性能

type Query {
        products(match : String) : [Product]   # a list of products
    }

    type Product {
        id : ID
        name : String
        description : String
        cost : Float
        tax : Float
    }

能夠在這個簡單的schema上執行一些簡單的查詢:this

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

而後,在Java代碼中須要爲Query.products字段綁定DataFetcher,以經過傳入的參數獲取product列表。設計

假設咱們有三個下游服務: 一個獲取產品信息,一個獲取產品成本信息,一個獲取產品稅信息。code

GraphQL - Java會在運行時調用dataFetcher獲取對象的數據,並將其映射爲schema中定義的類型。對象

在這個場景下,主要問題是:如何將三種不一樣來源的數據聚集爲一個單一的類型數據。ip

一種方式是,在cost和tax字段上添加dataFetcher,首先獲取產品列表,而後分別在每一個產品的cost、tax上執行dataFetcher。這種方式會比較容易維護,但也很容易產生N+1性能問題。
咱們也能夠在Query.products字段的dataFetcher上同時作三個下游信息的服務調用,而後建立一個統一數據展現視圖。以下所示:get

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字段)。graphql

有兩種方式能夠建立這種映射。一種是,經過使用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之間的映射。

相關文章
相關標籤/搜索