flexmodel-graphql
Flexmodel的GraphQL模块,自动为数据模型生成GraphQL Schema和查询接口。
功能特性
- 自动生成GraphQL Schema
- 支持查询、变更、订阅操作
- 支持分页、排序、过滤
- 支持关联查询和嵌套查询
- 支持聚合查询
- 类型安全的查询构建
引入依赖
<dependency>
<groupId>tech.wetech.flexmodel</groupId>
<artifactId>flexmodel-graphql</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
基本使用
初始化GraphQL
// 创建GraphQL提供者
GraphQLProvider graphQLProvider = new GraphQLProvider(sessionFactory);
graphQLProvider.init();
// 获取GraphQL实例
GraphQL graphQL = graphQLProvider.getGraphQL();
执行查询
// 定义查询
String query = """
query GetStudents($minAge: Int, $pageSize: Int) {
students(where: {age: {_gte: $minAge}}, page: {pageSize: $pageSize}) {
total
list {
id
studentName
age
gender
studentClass {
id
className
}
}
}
}
""";
// 设置变量
Map<String, Object> variables = new HashMap<>();
variables.put("minAge", 18);
variables.put("pageSize", 10);
// 执行查询
ExecutionInput executionInput = ExecutionInput.newExecutionInput()
.query(query)
.variables(variables)
.build();
ExecutionResult result = graphQL.execute(executionInput);
// 处理结果
if (result.getErrors().isEmpty()) {
Map<String, Object> data = result.getData();
// 处理查询结果
} else {
// 处理错误
result.getErrors().forEach(error -> {
System.err.println("GraphQL Error: " + error.getMessage());
});
}
执行变更
// 创建学生
String mutation = """
mutation CreateStudent($input: StudentInput!) {
createStudent(input: $input) {
id
studentName
age
gender
createdAt
}
}
""";
Map<String, Object> variables = new HashMap<>();
variables.put("input", Map.of(
"studentName", "张三",
"age", 18,
"gender", "MALE"
));
ExecutionInput executionInput = ExecutionInput.newExecutionInput()
.query(mutation)
.variables(variables)
.build();
ExecutionResult result = graphQL.execute(executionInput);
高级功能
自定义DataFetcher
// 创建自定义DataFetcher
public class CustomStudentDataFetcher extends FlexmodelAbstractDataFetcher {
public CustomStudentDataFetcher(SessionFactory sessionFactory) {
super(sessionFactory);
}
@Override
public Object get(DataFetchingEnvironment environment) {
// 自定义查询逻辑
String studentId = environment.getArgument("id");
return session.findById("Student", studentId);
}
}
// 注册自定义DataFetcher
graphQLProvider.registerDataFetcher("Query", "customStudent",
new CustomStudentDataFetcher(sessionFactory));
自定义指令
// 创建自定义指令
public class AuthDirective implements GraphQLDirective {
@Override
public String getName() {
return "auth";
}
@Override
public String getDescription() {
return "Authentication directive";
}
@Override
public List<GraphQLArgument> getArguments() {
return Arrays.asList(
GraphQLArgument.newArgument()
.name("required")
.type(Scalars.GraphQLBoolean)
.defaultValue(true)
.build()
);
}
}
// 注册指令
graphQLProvider.registerDirective(new AuthDirective());
错误处理
// 自定义错误处理
graphQLProvider.setErrorHandler(new GraphQLErrorHandler() {
@Override
public List<GraphQLError> processErrors(List<GraphQLError> errors) {
return errors.stream()
.map(error -> {
if (error instanceof ExceptionWhileDataFetching) {
ExceptionWhileDataFetching exceptionError = (ExceptionWhileDataFetching) error;
return GraphqlErrorBuilder.newError()
.message("数据获取错误: " + exceptionError.getException().getMessage())
.errorType(ErrorType.DataFetchingException)
.build();
}
return error;
})
.collect(Collectors.toList());
}
});
查询示例
基础查询
# 获取所有学生
query {
students {
id
studentName
age
gender
}
}
# 获取单个学生
query {
student(id: "1") {
id
studentName
age
gender
}
}
条件查询
# 年龄大于18的学生
query {
students(where: {age: {_gte: 18}}) {
id
studentName
age
}
}
# 姓张的学生
query {
students(where: {studentName: {_contains: "张"}}) {
id
studentName
}
}
分页查询
query {
students(
page: {current: 1, pageSize: 10}
sort: [{field: "age", direction: DESC}]
) {
total
list {
id
studentName
age
}
}
}
关联查询
query {
students {
id
studentName
studentClass {
id
className
classCode
}
}
}
聚合查询
query {
studentsAggregate(where: {age: {_gte: 18}}) {
count
avg {
age
}
sum {
age
}
min {
age
}
max {
age
}
}
}
变更示例
创建记录
mutation {
createStudent(input: {
studentName: "张三"
age: 18
gender: MALE
classId: 1
}) {
id
studentName
age
gender
createdAt
}
}
更新记录
mutation {
updateStudent(
id: "1"
input: {
studentName: "张三(已更新)"
age: 19
}
) {
id
studentName
age
updatedAt
}
}
删除记录
mutation {
deleteStudent(id: "1") {
id
studentName
}
}
配置选项
启用内省
graphQLProvider.setIntrospectionEnabled(true);
设置最大查询深度
graphQLProvider.setMaxQueryDepth(10);
设置最大查询复杂度
graphQLProvider.setMaxQueryComplexity(100);
启用查询缓存
graphQLProvider.setQueryCacheEnabled(true);
性能优化
查询优化
- 字段选择: 只选择需要的字段
- 分页查询: 使用分页避免大量数据查询
- 索引使用: 为常用查询字段创建索引
- 关联查询: 合理使用关联查询,避免N+1问题
缓存策略
// 启用查询缓存
graphQLProvider.setQueryCacheEnabled(true);
// 设置缓存大小
graphQLProvider.setQueryCacheSize(1000);
// 设置缓存过期时间
graphQLProvider.setQueryCacheExpireAfterWrite(Duration.ofMinutes(30));
最佳实践
- Schema设计: 合理设计GraphQL Schema
- 查询优化: 使用合适的查询条件和分页
- 错误处理: 妥善处理GraphQL错误
- 安全性: 实现适当的认证和授权
- 监控: 监控GraphQL查询性能
工具支持
GraphiQL
访问 /graphiql
可以使用GraphiQL交互式查询工具。
客户端库
推荐使用以下GraphQL客户端库:
- JavaScript/TypeScript: Apollo Client, Relay
- Java: Apollo Android, GraphQL Java
- Python: GQL, Python GraphQL Client
- Go: Machinebox GraphQL