Skip to content

Commit 4a031ba

Browse files
committed
Create dedicated section on projections
Closes gh-264
1 parent f34da25 commit 4a031ba

File tree

1 file changed

+72
-58
lines changed

1 file changed

+72
-58
lines changed

spring-graphql-docs/src/docs/asciidoc/index.adoc

Lines changed: 72 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -480,55 +480,13 @@ assertThat(books.get(0).getName()).isEqualTo("...");
480480
[[data]]
481481
== Data Integration
482482

483-
Spring for GraphQL is, in contrast to other GraphQL technologies that surface persistent
484-
data, not a data gateway that translates GraphQL queries into SQL or JSON queries.
485-
Instead, Spring for GraphQL is an API gateway that leverages existing Spring technology
486-
following common programming models to expose underlying data sources through GraphQL.
487-
488-
Domain-driven design is the suggested approach to manage complexity when using Spring Data.
489-
So by design, a GraphQL API built on top of Spring Data can leverage only what's already
490-
provided by an application.
491-
It, therefore, must adhere to the constraints of an aggregate.
492-
By definition, an aggregate is only valid if it is loaded in its entirety.
493-
Partially loaded aggregates may impose a limitation on aggregate functionality.
494-
495-
With Spring Data you can choose whether you want to let your aggregate participate as
496-
an underlying data model to be directly exposed as a GraphQL result, or whether you want to
497-
apply projections to your data model before returning it as a GraphQL operation result.
498-
499-
The advantage of using aggregates is that you do not require additional code to expose
500-
data through repositories. When processing a GraphQL operation, the integration layer
501-
transforms the field selection set into property paths. It provides these hints of which
502-
properties to materialize to the underlying Spring Data module that limits the field
503-
(or column) selection.
504-
505-
Sometimes, an already reduced set of fields can be useful when exposing data. Also, some
506-
arrangements might require transformations to be applied before data is returned for a
507-
GraphQL operation. Spring Data supports for these scenarios projections: Interface and DTO
508-
Projections.
483+
Spring for GraphQL lets you leverage existing Spring technology, following common
484+
programming models to expose underlying data sources through GraphQL.
509485

510-
Interface projections define a fixed set of properties to expose. Properties may or may
511-
not be `null`, depending on the query result. A plain, https://docs.spring.io/spring-data/commons/docs/current/reference/html/#projections.interfaces.closed[closed interface projection]
512-
can be useful if you cannot partially materialize the aggregate object but you still
513-
want to expose a subset of properties.
514-
515-
You can use interface projections to apply a lightweight set of data transformations,
516-
such as concatenations, computations or applying a static function to a property.
517-
518-
https://docs.spring.io/spring-data/commons/docs/current/reference/html/#projections.interfaces.open[Open projections]
519-
leverage Spring's `@Value` annotation and
520-
{spring-framework-ref-docs}/core.html#expressions[SpEL expressions]for transformations.
521-
522-
In both cases, interface projections define which properties to load from the underlying
523-
data source.
524-
525-
DTO projections offer the highest possible level of customization as you can place your
526-
transformation code either in the constructor or the getter method.
527-
528-
DTO projections materialize from a query where the individual properties are
529-
determined by the projection itself. DTO projections are commonly used with full-args
530-
constructors (e.g. Java records) and therefore they can only be constructed if all
531-
required fields (or columns) are part of the database query result.
486+
This section discusses an integration layer for Spring Data that provides an easy way to
487+
adapt a Querydsl or a Query by Example repository to a `DataFetcher`, including the
488+
option for automated detection and GraphQL Query registration for repositories marked
489+
with `@GraphQlRepository`.
532490

533491

534492

@@ -655,9 +613,12 @@ A repository may itself be an instance of `QuerydslBinderCustomizer`. This is au
655613
and transparently applied during <<data-querydsl-registration>>. However, when manually
656614
building a `QuerydslDataFetcher` you will need to use builder methods to apply it.
657615

658-
`QuerydslDataFetcher` supports
659-
https://docs.spring.io/spring-data/commons/docs/current/reference/html/#projections[interface and DTO projections]
660-
to transform query results before returning these for further GraphQL processing.
616+
`QuerydslDataFetcher` supports interface and DTO projections to transform query results
617+
before returning these for further GraphQL processing.
618+
619+
TIP: To learn what projections are, please refer to the
620+
https://docs.spring.io/spring-data/commons/docs/current/reference/html/#projections[Spring Data docs].
621+
To understand how to use projections in GraphQL, please see <<data-projections>>.
661622

662623
To use Spring Data projections with Querydsl repositories, create either a projection interface
663624
or a target DTO class and configure it through the `projectAs` method to obtain a
@@ -691,7 +652,7 @@ or a target DTO class and configure it through the `projectAs` method to obtain
691652

692653

693654
[[data-querydsl-registration]]
694-
==== Auto Registration
655+
==== Auto-Registration
695656

696657
If a repository is annotated with `@GraphQlRepository`, it is automatically registered
697658
for queries that do not already have a registered `DataFetcher` and whose return type
@@ -713,7 +674,6 @@ detects `@GraphQlRepository` beans and uses them to initialize the
713674

714675

715676

716-
717677
[[data-querybyexample]]
718678
=== Query by Example
719679

@@ -763,9 +723,12 @@ it is supported, so no extra setup is required to enable it.
763723
[[data-querybyexample-customizations]]
764724
==== Customizations
765725

766-
`QueryByExampleDataFetcher` supports
767-
https://docs.spring.io/spring-data/commons/docs/current/reference/html/#projections[interface and DTO projections]
768-
to transform query results before returning these for further GraphQL processing.
726+
`QueryByExampleDataFetcher` supports interface and DTO projections to transform query
727+
results before returning these for further GraphQL processing.
728+
729+
TIP: To learn what projections are, please refer to the
730+
https://docs.spring.io/spring-data/commons/docs/current/reference/html/#projections[Spring Data docs].
731+
To understand how to use projections in GraphQL, please see <<data-projections>>.
769732

770733
To use Spring Data projections with Query by Example repositories, create either a projection interface
771734
or a target DTO class and configure it through the `projectAs` method to obtain a
@@ -797,9 +760,8 @@ or a target DTO class and configure it through the `projectAs` method to obtain
797760
----
798761

799762

800-
801763
[[data-querybyexample-registration]]
802-
==== Auto Registration
764+
==== Auto-Registration
803765

804766
If a repository is annotated with `@GraphQlRepository`, it is automatically registered
805767
for queries that do not already have a registered `DataFetcher` and whose return type
@@ -818,6 +780,58 @@ detects `@GraphQlRepository` beans and uses them to initialize the
818780

819781

820782

783+
[[data-projections]]
784+
=== Selection Set vs Projections
785+
786+
A common question that arises is, how GraphQL selection sets compare to
787+
https://docs.spring.io/spring-data/commons/docs/current/reference/html/#projections[Spring Data projections]
788+
and what roles do each play?
789+
790+
The short answer is that Spring for GraphQL is not a data gateway that translates GraphQL
791+
queries directly into SQL or JSON queries. Instead, it lets you leverage existing Spring
792+
technology and does not assume a one for one mapping between the GraphQL schema and the
793+
underlying data. That is why is there is room for both client-driven selection and for
794+
server-side transformation of the data model.
795+
796+
To understand better, consider that Spring Data promotes domain-driven (DDD) design as
797+
the recommended approach to manage complexity in the data layer. In DDD, it is important
798+
to adhere to the constraints of an aggregate. By definition an aggregate is valid only if
799+
loaded in its entirety, since a partially loaded aggregate may impose a limitation on
800+
aggregate functionality.
801+
802+
In Spring Data you can choose whether you want your aggregate be exposed as is, or
803+
whether to apply projections to the data model before returning it. Sometimes it's enough
804+
to do the former and by default, the <<data-querydsl>> and <<data-querybyexample>>
805+
integrations rely on the GraphQL field selection set to provide property path hints to
806+
the underlying Spring Data module to limit the field (or column) selection.
807+
808+
In other cases, it's useful to reduce or even transform the underlying data model in
809+
order to adapt to the GraphQL schema, and Spring Data supports these through Interface
810+
and DTO Projections.
811+
812+
Interface projections define a fixed set of properties to expose. Properties may or may
813+
not be `null`, depending on the data store query result. There are two kinds of interface
814+
projections both of which define which properties to load from the underlying data source:
815+
816+
- https://docs.spring.io/spring-data/commons/docs/current/reference/html/#projections.interfaces.closed[Closed interface projections]
817+
are helpful if you cannot partially materialize the aggregate object, but you still
818+
want to expose a subset of properties.
819+
- https://docs.spring.io/spring-data/commons/docs/current/reference/html/#projections.interfaces.open[Open interface projections]
820+
leverage Spring's `@Value` annotation and
821+
{spring-framework-ref-docs}/core.html#expressions[SpEL] expressions to apply lightweight
822+
data transformations, such as concatenations, computations, or to apply a static function
823+
to a property.
824+
825+
DTO projections offer the highest possible level of customization as you can place your
826+
transformation code either in the constructor or the getter method.
827+
828+
DTO projections materialize from a query where the individual properties are
829+
determined by the projection itself. DTO projections are commonly used with full-args
830+
constructors (e.g. Java records), and therefore they can only be constructed if all
831+
required fields (or columns) are part of the database query result.
832+
833+
834+
821835

822836
[[controllers]]
823837
== Annotated Controllers

0 commit comments

Comments
 (0)