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之间的映射。