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
使用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之間的映射。