基于graphql-java 8.0动态解析多Schema的条件数据获取问题
解决方案:基于contentTypeId动态返回Fish/Fruit类型数据
针对你用com.graphql-java:graphql-java:8.0开发的场景,要根据ResultOne的contentTypeId动态关联不同类型的额外数据,咱们可以通过联合类型(Union Type) + 类型解析器(TypeResolver) + **自定义数据获取器(DataFetcher)**来实现,具体步骤如下:
1. 调整Schema定义
首先扩展你的Schema,加入联合类型和额外字段,明确动态数据的类型范围:
# 定义联合类型,限定只能返回Fish或Fruit union FishOrFruit = Fish | Fruit # Fish类型的具体字段 type Fish { id: ID! name: String! habitat: String } # Fruit类型的具体字段 type Fruit { id: ID! name: String! season: String } extend type Query { search(name: String, category: String): [ResultOne] } type ResultOne { contentTypeId: Int! # 新增字段,用于返回动态类型的额外数据 additionalData: FishOrFruit # 保留你原有的其他业务字段 # ... }
2. Java代码实现核心逻辑
2.1 定义对应的数据实体类
先创建和Schema匹配的Java实体,方便后续数据传递和处理:
// ResultOne实体,对应Schema中的ResultOne类型 public class ResultOne { private Integer contentTypeId; private String otherBizField; // 替换成你的实际业务字段 // getter、setter方法 } // Fish实体,对应Schema中的Fish类型 public class Fish { private String id; private String name; private String habitat; // getter、setter方法 } // Fruit实体,对应Schema中的Fruit类型 public class Fruit { private String id; private String name; private String season; // getter、setter方法 }
2.2 实现类型解析器(TypeResolver)
类型解析器的作用是告诉GraphQL:当前FishOrFruit联合类型实际返回的是哪一种具体类型,确保查询能正确匹配字段:
import graphql.schema.TypeResolver; import graphql.schema.DataFetchingEnvironment; import graphql.schema.GraphQLObjectType; public class FishOrFruitTypeResolver implements TypeResolver { @Override public GraphQLObjectType getType(DataFetchingEnvironment env) { Object source = env.getSource(); if (source instanceof Fish) { return env.getGraphQLSchema().getObjectType("Fish"); } else if (source instanceof Fruit) { return env.getGraphQLSchema().getObjectType("Fruit"); } throw new RuntimeException("无法识别FishOrFruit联合类型的具体实例"); } }
2.3 实现额外数据的DataFetcher
这个DataFetcher会根据ResultOne的contentTypeId,触发对应的数据获取逻辑(比如从数据库、第三方接口拉取数据):
import graphql.schema.DataFetcher; import graphql.schema.DataFetchingEnvironment; public class AdditionalDataFetcher implements DataFetcher<Object> { @Override public Object get(DataFetchingEnvironment env) { ResultOne resultOne = env.getSource(); Integer contentTypeId = resultOne.getContentTypeId(); // 这里替换成你的实际数据获取逻辑 if (contentTypeId == 1) { Fish salmon = new Fish(); salmon.setId("fish_001"); salmon.setName("三文鱼"); salmon.setHabitat("深海"); return salmon; } else if (contentTypeId == 2) { Fruit apple = new Fruit(); apple.setId("fruit_001"); apple.setName("红富士"); apple.setSeason("秋季"); return apple; } return null; // 或者根据业务需求返回默认值 } }
2.4 整合Schema与组件
最后把这些组件注册到Schema构建流程中,确保GraphQL能识别并调用:
import graphql.GraphQL; import graphql.schema.GraphQLSchema; import graphql.schema.idl.RuntimeWiring; import graphql.schema.idl.SchemaGenerator; import graphql.schema.idl.SchemaParser; import graphql.schema.idl.TypeDefinitionRegistry; import java.io.File; public class GraphQLServiceConfig { public GraphQL buildGraphQL() throws Exception { // 加载你的Schema文件(也可以用字符串直接定义) File schemaFile = new File("src/main/resources/schema.graphqls"); TypeDefinitionRegistry typeRegistry = new SchemaParser().parse(schemaFile); RuntimeWiring wiring = RuntimeWiring.newRuntimeWiring() // 注册联合类型的解析器 .type("FishOrFruit", typeWiring -> typeWiring.typeResolver(new FishOrFruitTypeResolver())) // 为ResultOne的additionalData字段绑定数据获取器 .type("ResultOne", typeWiring -> typeWiring.dataFetcher("additionalData", new AdditionalDataFetcher())) // 注册Query中search字段的数据获取器(你的原有业务逻辑) .type("Query", typeWiring -> typeWiring.dataFetcher("search", new SearchDataFetcher())) .build(); GraphQLSchema schema = new SchemaGenerator().makeExecutableSchema(typeRegistry, wiring); return GraphQL.newGraphQL(schema).build(); } }
3. 测试查询示例
现在你可以发起如下查询,GraphQL会自动根据contentTypeId返回对应类型的额外数据:
query { search(name: "测试") { contentTypeId additionalData { ... on Fish { id name habitat } ... on Fruit { id name season } } } }
当contentTypeId为1时,会返回Fish的字段;为2时返回Fruit的字段,完全匹配你的业务需求~
内容的提问来源于stack exchange,提问作者Md. Hasan Basri
相关产品推荐
相关产品推荐

