GraphQL Java - Data Fetcher

A, graphql how to get data

Each field has a defined graphql graphql.schema.DataFetcher associated.

Some field uses data fetcher custom code, for accessing the database fields, and acquires information from the database. Most field names and field use only plain old Java objects (POJO) model to retrieve data from memory object returned to retrieve data.

In other graphq achieve them, when Data Fetcher will be called resolvers.

Suppose a type defined as follows:

    type Query {
        products(match : String) : [Product]   # a list of products
    }

    type Product {
        id : ID
        name : String
        description : String
        cost : Float
        tax : Float
        launchDate(dateFormat : String = "dd, MMM, yyyy') : String
    }

Query.products field has a Data Fetcher, Product type for each field, too.

Data Query.products Fetcher field which may be a more complex Data Fetcher, Product object includes reading from a database operation. It uses an optional parameter match, in turn, can result in products of filter objects.

Possible examples thereof are as follows:

        DataFetcher productsDataFetcher = new DataFetcher<List<ProductDTO>>() {
            @Override
            public List<ProductDTO> get(DataFetchingEnvironment environment) {
                DatabaseSecurityCtx ctx = environment.getContext();

                List<ProductDTO> products;
                String match = environment.getArgument("match");
                if (match != null) {
                    products = fetchProductsFromDatabaseWithMatching(ctx, match);
                } else {
                    products = fetchAllProductsFromDatabase(ctx);
                }
                return products;
            }
        };

Each DataFetcher are passed a graphql.schema.DataFetchingEnvironment object that contains fields are obtained, and other information available to the parameter fields, such as the type of field, type of parent, the root object query or query context object.

Please note that the above data information on how to use the context object code as application-specific security handle to access the database. This is a common technique to provide lower calling context.

Once we have ProductDTO object list, we usually do not need to obtain a special use data on each field. graphql-java comes with a smart graphql.schema.PropertyDataFetcher, it knows how to follow POJO model based on the field names. In the example above, there is a name field, so it tries to find public String getName () POJO method to get the data.

graphql.schema.PropertyDataFetcher default data is automatically associated with each field in the case where the acquirer.

However, you can still access the DTO method graphql.schema.DataFetchingEnvironment. This allows the adjustment values ​​prior to transmission. For example, the above we have a launchDate field, it takes an optional parameter dateFormat. We can make this date ProductDTO logical format applied to the desired format.

    class ProductDTO {

        private ID id;
        private String name;
        private String description;
        private Double cost;
        private Double tax;
        private LocalDateTime launchDate;

        // ...

        public String getName() {
            return name;
        }

        // ...

        public String getLaunchDate(DataFetchingEnvironment environment) {
            String dateFormat = environment.getArgument("dateFormat");
            return yodaTimeFormatter(launchDate,dateFormat);
        }
    }

Second, the customized PropertyDataFetcher

As described above, graphql.schema.PropertyDataFetcher graphql-java default data acquired in the field, it will use the standard mode to get the object field values.

It used to support a Java POJO method and Map methods. By default, it is assumed that for graphql field fieldX, if supported object is a Map, it can find the name of the POJO properties or fieldX called fieldX mapkeys.

However, there may be subtle differences between objects when graphql naming schema naming and run. For example, suppose Product.description actually supports Java objects at run time expressed as getDesc ().

If SDL specified schema, you can use this instruction instructs @fetch remapping.

    directive @fetch(from : String!) on FIELD_DEFINITION

    type Product {
        id : ID
        name : String
        description : String @fetch(from:"desc")
        cost : Float
        tax : Float
    }

This will tell graphql.schema.PropertyDataFetcher use the property name desc while acquiring data graphql field named description.

If the code manually configured schema, then you only need to be specified directly in the code.

        GraphQLFieldDefinition descriptionField = GraphQLFieldDefinition.newFieldDefinition()
                .name("description")
                .type(Scalars.GraphQLString)
                .build();

        GraphQLCodeRegistry codeRegistry = GraphQLCodeRegistry.newCodeRegistry()
                .dataFetcher(
                        coordinates("ObjectType", "description"),
                        PropertyDataFetcher.fetching("desc"))
                .build();

三、DataFetchingEnvironment

Each data acquirer are passed a graphql.schema.DataFetchingEnvironment object, which allows it to learn more about the content and the acquired parameters are provided. Here are some of the more interesting parts of DataFetchingEnvironment.

  • T getSource (): source object is used to obtain information field. It is the object extracted result value of the parent field. Under normal circumstances, it is an object DTO memory, so a simple POJO getter for a field value. In more complex cases, you can check it to see how to get specific information of the current field. When performing tree graphql field, each field value returned will be the source of the object on which the lower sub-fields.
  • T getRoot (): This special object is used to seed the graphql query. For the top field, the root and the source are the same. The root object will never change during the inquiry, and may be null (do not use).
  • Map <String, Object> getArguments (): indicates the value of the parameter has been provided on the field and those transmitted from the variable parameter, the AST literal analysis values ​​and default parameters. Argument may be used to control the parameters of a particular field value it returns.
  • T getContext (): Object context is set when the first query is executed, and remains constant over the life cycle of the query. Context can be any value, often used to provide some of the required call context when trying to get field data for each data fetcher. For example, the current user credentials or connection parameters can be included in the database context object to data fetcher layer calls for business. As graphql system designer, is one of the key design decisions on how to use context. In some cases, designers rely on the use of the framework, automatically injected into the context data extractor, in which case it is not necessary to use.
  • ExecutionStepInfo getExecutionStepInfo (): type information field, all field types of information to build the query is executed.
  • DataFetchingFieldSelectionSet getSelectionSet (): Select the set indicates "selected" in the field currently being executed subfield.
  • ExecutionId getExecutionId (): each query has a unique id. It may be used to mark on the log of each individual query.

3.1 ExecutionStepInfo

Graphql during the execution of the query, create a call tree that contains fields and their types. graphql.execution.ExecutionStepInfo.getParentTypeInfo allows you to traverse up the tree, and see which type or field starting execution of the current field.

graphql.execution.ExecutionStepInfo.getPath method returns a path representation. This is useful for debugging query log or print.

There are some helper methods, you can get a list Nonnull or internal packaging types primitive types.

3.2 DataFetchingFieldSelectionSet

Suppose a query as follows

    query {
        products {
            # the fields below represent the selection set
            name
            description
            sellingLocations {
                state
            }
        }
    }

Subfield products field indicates the selected set of fields. Understand the required sub-selection may be useful, therefore data fetcher can optimize data access query. For example, SQL support system may be able to use the selected set of fields has been requested to retrieve only the column.

In the above example, we require sellingLocations information, so we can be more efficient data when we inquired on product information and sales location information access queries.

Guess you like

Origin www.cnblogs.com/pku-liuqiang/p/11502414.html