@@ -314,7 +314,7 @@ Spring GraphQL exposes a `BatchLoaderRegistry` that accepts and stores registrat
314
314
batch loading functions. The `ExecutionGraphQlService` accepts the registry as input and
315
315
uses it to make per request `DataLoader` registrations. A `DataFetcher` then looks up the
316
316
`DataLoader` for an entity and uses it to load instances, or in an annotated controller,
317
- simply declare a <<controllers-data-loader,DataLoader argument>> to access the
317
+ simply declare a <<controllers-schema-mapping- data-loader,DataLoader argument>> to access the
318
318
registered loader. Annotated controllers also support a
319
319
<<controllers-batch-mapping,@BatchMapping>> that avoids the need to use `DataLoader`
320
320
directly.
@@ -447,8 +447,8 @@ and adds all `RuntimeWiringConfigurer` beans to `GraphQlSource.Builder` and that
447
447
support for annotated ``DataFetcher``s, see <<boot-graphql-runtimewiring>>.
448
448
449
449
450
- [[controllers-mapping]]
451
- === Mapping
450
+ [[controllers-schema- mapping]]
451
+ === `@SchemaMapping`
452
452
453
453
The `@SchemaMapping` annotation maps a handler method to a field in the GraphQL schema
454
454
and declares it to be the `DataFetcher` for that field. The annotation can specify the
@@ -524,148 +524,47 @@ for fields under the Query, Mutation, and Subscription types respectively. For e
524
524
}
525
525
----
526
526
527
-
528
- [[controllers-batch-mapping]]
529
- === Batch Mapping
530
-
531
- <<execution-batching>> addresses the N+1 select problem through the use of an
532
- `org.dataloader.DataLoader` to defer the loading of individual entity instances, so they
533
- can be loaded together. For example:
534
-
535
- [source,java,indent=0,subs="verbatim,quotes"]
536
- ----
537
- @Controller
538
- public class BookController {
539
-
540
- public BookController(BatchLoaderRegistry registry) {
541
- registry.forTypePair(Long.class, Author.class).registerMappedBatchLoader((authorIds, env) -> {
542
- // return Map<Long, Author>
543
- });
544
- }
545
-
546
- @SchemaMapping
547
- public CompletableFuture<Author> author(Book book, DataLoader<Long, Author> loader) {
548
- return loader.load(book.getAuthorId());
549
- }
550
-
551
- }
552
- ----
553
-
554
- For the straight-forward case of loading an associated entity, shown above, the
555
- `@SchemaMapping` method does nothing more than delegate to the `DataLoader`. This is
556
- boilerplate that can be avoided with a `@BatchMapping` method. For example:
557
-
558
- [source,java,indent=0,subs="verbatim,quotes"]
559
- ----
560
- @Controller
561
- public class BookController {
562
-
563
- @BatchMapping
564
- public Mono<Map<Book, Author>> author(List<Book> books) {
565
- // ...
566
- }
567
- }
568
- ----
569
-
570
- The above becomes a batch loading function in the `BatchLoaderRegistry`
571
- where keys are `Book` instances and the loaded values their authors. In addition, a
572
- `DataFetcher` is also transparently bound to the `author` field of the type `Book`, which
573
- simply delegates to the `DataLoader` for authors, given its source/parent `Book` instance.
574
-
575
- [TIP]
576
- ====
577
- To be used as a unique key, `Book` must implement `hashcode` and `equals`.
578
- ====
579
-
580
- By default, the field name defaults to the method name, while the type name defaults to
581
- the simple class name of the input `List` element type. Both can be customized through
582
- annotation attributes. The type name can also be inherited from a class level
583
- `@SchemaMapping`.
584
-
585
- A `@BatchMapping` method can also return a sequence of instances, and that needs to match
586
- the order of the source/parent objects:
587
-
588
- [source,java,indent=0,subs="verbatim,quotes"]
589
- ----
590
- @Controller
591
- public class BookController {
592
-
593
- @BatchMapping
594
- public Flux<Author> author(List<Book> books) {
595
- // ...
596
- }
597
- }
598
- ----
599
-
600
- It is possible to use imperative method signatures too, i.e. returning `Map<K, V>` or
601
- `List<V>`, which can be useful when there are no remote calls to make.
602
-
603
- `BatchMapping` methods support two types of arguments:
604
-
605
- [cols="1,2"]
606
- |===
607
- | Method Argument | Description
608
-
609
- | `List<K>`
610
- | The source/parent objects.
611
-
612
- | `BatchLoaderEnvironment`
613
- | The environment that is available in GraphQL Java to a
614
- `org.dataloader.BatchLoaderWithContext`.
615
-
616
- |===
617
-
618
-
619
-
620
-
621
- [[controllers-methods]]
622
- === Handler Methods
623
-
624
527
`@SchemaMapping` handler methods have flexible signatures and can choose from a range of
625
528
method arguments and return values..
626
529
627
530
628
- [[controllers-arguments ]]
629
- ==== Method Arguments
531
+ [[controllers-schema-mapping-signature ]]
532
+ ==== Method Signature
630
533
631
- Annotated handler methods can choose from one of the following method arguments:
534
+ Schema mapping handler methods can have any of the following method arguments:
632
535
633
536
[cols="1,2"]
634
537
|===
635
538
| Method Argument | Description
636
539
637
540
| `@Argument`
638
541
| For access to field arguments with conversion.
639
- See <<controllers-argument>>.
542
+ See <<controllers-schema-mapping -argument>>.
640
543
641
544
| Source
642
545
| For access to the source (i.e. parent/container) instance of the field.
643
- See <<controllers-source>>.
546
+ See <<controllers-schema-mapping -source>>.
644
547
645
548
| `DataLoader`
646
549
| For access to a `DataLoader` in the `DataLoaderRegistry`.
647
- See <<controllers-data-loader>>.
550
+ See <<controllers-schema-mapping- data-loader>>.
648
551
649
552
| `GraphQLContext`
650
553
| For access to the context from the `DataFetchingEnvironment`.
651
- See <<controllers-graphql-context>>.
554
+ See <<controllers-schema-mapping- graphql-context>>.
652
555
653
556
| `DataFetchingEnvironment`
654
557
| For direct access to the underlying `DataFetchingEnvironment`.
655
- See <<controllers-environment>>.
558
+ See <<controllers-schema-mapping- environment>>.
656
559
657
560
|===
658
561
562
+ Schema mapping handler methods can return any value, including Reactor `Mono` and
563
+ `Flux` as described in <<execution-reactive-datafetcher>>.
659
564
660
- [[controllers-return-values]]
661
- ==== Return Values
662
-
663
- Annotated handler methods can return any value, including Reactor `Mono` and `Flux` as
664
- described in <<execution-reactive-datafetcher>>.
665
565
666
566
667
-
668
- [[controllers-argument]]
567
+ [[controllers-schema-mapping-argument]]
669
568
==== `@Argument`
670
569
671
570
In GraphQL Java, the `DataFetchingEnvironment` provides access to field-specific argument
@@ -704,7 +603,7 @@ You can use `@Argument` on a `Map<String, Object>` argument, to obtain all argum
704
603
values. The name attribute on `@Argument` must not be set.
705
604
706
605
707
- [[controllers-source]]
606
+ [[controllers-schema-mapping- source]]
708
607
==== Source
709
608
710
609
In GraphQL Java, the `DataFetchingEnvironment` provides access to the source (i.e.
@@ -727,8 +626,15 @@ The source method argument also helps to determine the type name for the mapping
727
626
If the simple name of the Java class matches the GraphQL type, then there is no need to
728
627
explicitly specify the type name in the `@SchemaMapping` annotation.
729
628
629
+ [TIP]
630
+ ====
631
+ A <<controllers-batch-mapping>> handler method can batch load all authors for a query,
632
+ given a list of source/parent books objects.
633
+ ====
634
+
635
+
730
636
731
- [[controllers-data-loader]]
637
+ [[controllers-schema-mapping- data-loader]]
732
638
==== `DataLoader`
733
639
734
640
When you register a batch loading function for an entity, as explained in
@@ -769,21 +675,117 @@ instead.
769
675
====
770
676
771
677
772
- [[controllers-graphql-context]]
678
+ [[controllers-schema-mapping- graphql-context]]
773
679
==== `GraphQLContext`
774
680
775
681
To access the `GraphQLContext` from the `DataFetchingEnvironment`, declare a method
776
682
parameter of the same type.
777
683
778
684
779
- [[controllers-environment]]
685
+ [[controllers-schema-mapping- environment]]
780
686
==== `DataFetchingEnvironment`
781
687
782
688
To access the `DataFetchingEnvironment` directly, declare a method parameter of the same
783
689
type.
784
690
785
691
786
692
693
+ [[controllers-batch-mapping]]
694
+ === `@BatchMapping`
695
+
696
+ <<execution-batching>> addresses the N+1 select problem through the use of an
697
+ `org.dataloader.DataLoader` to defer the loading of individual entity instances, so they
698
+ can be loaded together. For example:
699
+
700
+ [source,java,indent=0,subs="verbatim,quotes"]
701
+ ----
702
+ @Controller
703
+ public class BookController {
704
+
705
+ public BookController(BatchLoaderRegistry registry) {
706
+ registry.forTypePair(Long.class, Author.class).registerMappedBatchLoader((authorIds, env) -> {
707
+ // return Map<Long, Author>
708
+ });
709
+ }
710
+
711
+ @SchemaMapping
712
+ public CompletableFuture<Author> author(Book book, DataLoader<Long, Author> loader) {
713
+ return loader.load(book.getAuthorId());
714
+ }
715
+
716
+ }
717
+ ----
718
+
719
+ For the straight-forward case of loading an associated entity, shown above, the
720
+ `@SchemaMapping` method does nothing more than delegate to the `DataLoader`. This is
721
+ boilerplate that can be avoided with a `@BatchMapping` method. For example:
722
+
723
+ [source,java,indent=0,subs="verbatim,quotes"]
724
+ ----
725
+ @Controller
726
+ public class BookController {
727
+
728
+ @BatchMapping
729
+ public Mono<Map<Book, Author>> author(List<Book> books) {
730
+ // ...
731
+ }
732
+ }
733
+ ----
734
+
735
+ The above becomes a batch loading function in the `BatchLoaderRegistry`
736
+ where keys are `Book` instances and the loaded values their authors. In addition, a
737
+ `DataFetcher` is also transparently bound to the `author` field of the type `Book`, which
738
+ simply delegates to the `DataLoader` for authors, given its source/parent `Book` instance.
739
+
740
+ [TIP]
741
+ ====
742
+ To be used as a unique key, `Book` must implement `hashcode` and `equals`.
743
+ ====
744
+
745
+ By default, the field name defaults to the method name, while the type name defaults to
746
+ the simple class name of the input `List` element type. Both can be customized through
747
+ annotation attributes. The type name can also be inherited from a class level
748
+ `@SchemaMapping`.
749
+
750
+ [[controllers-batch-mapping-signature]]
751
+ ==== Method Signature
752
+
753
+ Batch mapping methods support two types of arguments:
754
+
755
+ [cols="1,2"]
756
+ |===
757
+ | Method Argument | Description
758
+
759
+ | `List<K>`
760
+ | The source/parent objects.
761
+
762
+ | `BatchLoaderEnvironment`
763
+ | The environment that is available in GraphQL Java to a
764
+ `org.dataloader.BatchLoaderWithContext`.
765
+
766
+ |===
767
+
768
+ Batch mapping methods can return:
769
+
770
+ [cols="1,2"]
771
+ |===
772
+ | Return Type | Description
773
+
774
+ | `Mono<Map<K,V>>`
775
+ | A map with parent objects as keys, and batch loaded objects as values.
776
+
777
+ | `Flux<V>`
778
+ | A sequence of batch loaded objects that must be in the same order as the source/parent
779
+ objects passed into the method.
780
+
781
+ | `Map<K,V>`, `Flux<V>`
782
+ | Imperative variants, e.g. without remote calls to make.
783
+
784
+ |===
785
+
786
+
787
+
788
+
787
789
[[security]]
788
790
== Security
789
791
0 commit comments