Graphql-Java实践(二)-变更

这次来说一下相对应 “增删改的” Mutation操作,也是使用对应的DataFetcher,只不过增加了一个增删改的操作后返回查询结果罢了,老样子来看一个例子,IDL方式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
schema {
    mutation: userMutation
    query: userQuery
}
type userQuery {
    user(id: Int): [User]
}
type userMutation {
    createUser(addUser:UserInput): [User]
}
input UserInput{
    id: Int
    age: Int
    userName: String!
    dogs: [DogInput]
}
input DogInput {
    id: Int
    dogName: String!
}
type User {
    id: Int
    age: Int
    userName: String!
    dogs(dogId:Int): [Dog]
}
type Dog {
    id: Int
    dogName: String!
}

 

所有的入参除了基础标量类型以外,需要使用input类型来指代自定义类型,同时在定义Mutation的同时,必须有1个Query操作,不然执行Schema校验的时候会报错,不知道是什么原因,不过项目中肯定是Mutation与Query共存的,也就不深究了。另外大家看到在新增操作的地方,参数我使用了一个自定义input对象。如果是基础类型的话,方式与Query一直;但如果使用了自定义类型,在进行Variable设置的时候是有一定区别的,具体看Java代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
//构建一个运行时Java语义 绑定schema,包括(datafetcher、typeResolver、customScalar)
    private static RuntimeWiring buildRuntimeWiring() {
        //return RuntimeWiring.newRuntimeWiring().wiringFactory(new EchoingWiringFactory()).build();
        return RuntimeWiring.newRuntimeWiring()
                // this uses builder function lambda syntax
                .type("userMutation", typeWiring -> typeWiring
                                .dataFetcher("createUser", environment -> {
                                    //上一级对象数据 environment.getSource()
                                    //Map<String,Object> environment.getArguments()
                                    //环境上下文,整个查询冒泡中都可以使用 environment.getContext()
                                    //只能获取到LinkedHashMap,无法直接转换成对象
                                    Map<String,Objects> paramMap = environment.getArgument("addUser");
                                    System.out.println("argument:paramMap=" + paramMap);
                                    // repository 处理
                                    return getUsers(123);
                                })
                ).type("userQuery", typeWiring -> typeWiring
                                .dataFetcher("user", environment -> {
                                    //上一级对象数据 environment.getSource()
                                    //Map<String,Object> environment.getArguments()
                                    //环境上下文,整个查询冒泡中都可以使用 environment.getContext()
                                    Integer id = environment.getArgument("id");
                                    System.out.println("argument:id=" + id);
                                    // repository 处理
                                    return getUsers(id);
                                })
                ).type("User", typeWiring -> typeWiring
                        .dataFetcher("dogs", environment -> {
                            //获取父对象
                            User user = environment.getSource();
                            int userId = user.getId();
                            System.out.println("dogs outside userId = " + userId);
                            Integer paramDogId = environment.getArgument("dogId");
                            System.out.println("dogs inside dogId = " + paramDogId);
                            //模拟rpc调用
                            List<Dog> dogs = Lists.newArrayList();
                            return dogs;
                        }))
                .build();
    }
    //schema
    public static void mainExec() throws InterruptedException {
        //创建Schema
        SchemaParser schemaParser = new SchemaParser();
        SchemaGenerator schemaGenerator = new SchemaGenerator();

        File schemaFile = loadSchema("graphql/userMutation.graphqls");

        TypeDefinitionRegistry typeRegistry = schemaParser.parse(schemaFile);
        RuntimeWiring wiring = buildRuntimeWiring();
        GraphQLSchema schema = schemaGenerator.makeExecutableSchema(typeRegistry, wiring);
        //测试输出
        GraphQL graphQL = GraphQL.newGraphQL(schema).build();
        Map<String,Object> variable = Maps.newHashMap();
        variable.put("uuu",MutationVariableHandler.getVariablesMapFromString(JSON.toJSONString(getUsers(123).get(0))));
        //变量名不要和类型名一样,不然好像有点问题
        ExecutionInput executionInput = ExecutionInput.newExecutionInput().
                variables(variable).
                query("mutation userMutation($uuu:UserInput){createUser(addUser:$uuu)" +
                        "{id,age,dogs{id,dogName}}}").build();
        ExecutionResult result = graphQL.execute(executionInput);
        Map<String, Object> data = result.getData();
        List errors = result.getErrors();
        System.out.println(data);
        System.out.println("errors = "+errors);
    }

 

Console:
argument:paramMap={id=1, age=0, userName=bf2e46b6-dcf3-47e2-a14c-a305e38d3926, dogs=[{id=100, dogName=Dog11e0e22c-0b44-4018-968f-d655e64d4260}]}
dogs outside userId = 1
dogs inside dogId = null
{createUser=[{id=1, age=7, dogs=[]}]}

uuu是我自己定义的类型为UserInput的Variable,在成功执行之前,我试过在map的value里放过json字符串、user对象,但GraphQL引擎执行的时候,会报如下错误:
graphql.schema.CoercingParseValueException: Variable ‘uuu’ has an invalid value. Expected type ‘Map’ but was ‘User’. Variables for input objects must be an instance of type ‘Map’.
看了下源码,发现在使用Variable进行query执行的时候,自定义类型必须以Map<String,Object>的形式入参,这就很尴尬了,贴上现在的转换方式,比较傻。但如果集合Web项目的话,入参可以直接转换成Map,应该会好一点:

1
2
3
4
5
6
7
8
9
10
private static ObjectMapper jacksonObjectMapper = new ObjectMapper();
    private static TypeReference<HashMap<String, Object>> typeRefReadJsonString = new TypeReference<HashMap<String, Object>>() {
    };
public static Map<String, Object> getVariablesMapFromString(String variablesFromRequest) {
        try {
            return jacksonObjectMapper.readValue(variablesFromRequest, typeRefReadJsonString);
        } catch (IOException exception) {
            throw new GraphQLException("Cannot parse variables", exception);
        }
    }

 

说实话,写到这边个人认为Mutation只是单纯一个语义标识的操作类型,其实在Query的DataFetcher中也可以做插入和修改操作;而且Mutation同时也需要返回结果,和Query也类似。

graphql-java 是 GraphQLJava 实现。这个库的目标是用于真实的生产环境。graphql-java 解析和执行查询 GraphQL 。它并不真正获取任何数据的:数据来源于执行回调或提供静态数据。graphql-java 的 "hello world":import graphql.schema.GraphQLObjectType; import graphql.schema.GraphQLSchema; import static graphql.Scalars.GraphQLString; import static graphql.schema.GraphQLFieldDefinition.newFieldDefinition; import static graphql.schema.GraphQLObjectType.newObject; public class HelloWorld {     public static void main(String[] args) {         GraphQLObjectType queryType = newObject()                         .name("helloWorldQuery")                         .field(newFieldDefinition()                                 .type(GraphQLString)                                 .name("hello")                                 .staticValue("world")                                 .build())                         .build();         GraphQLSchema schema = GraphQLSchema.newSchema()                         .query(queryType)                         .build();         Map result = new GraphQL(schema).execute("{hello}").getData();         System.out.println(result);         // Prints: {hello=world}     } } 标签:graphql
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值