Schema-first-design och typmappning
Definiera ett GraphQL-schema och mappa typer, queries och mutationer till Java-controller-metoder.
Schema-first-design och typmappning är en gratis lektion i Spring Boot 4 – komplett guide på CoddyKit. Detta är lektion 1 av 4. Du kan läsa vilka 3 lektioner som helst i den här lärvägen kostnadsfritt i sin helhet – därefter låser CoddyKit PRO upp alla lektioner, plus praktisk övning med en inbyggd kodredigerare och en AI-lärare dygnet runt. Den ingår i lärvägen för Spring Boot 4 – komplett guide, och Era framsteg synkroniseras mellan webben och CoddyKit-appen. Kursen i Spring Boot 4 – komplett guide innehåller totalt 4 lektioner.
Schema först i Spring för GraphQL
Spring for GraphQL är schema-first: Ni beskriver ert API i en fil med Schema Definition Language (SDL) för .graphql, och Er Java-kod mappas mot det.
- schemat är den enda källan till sanning för API-kontraktet.
- Klienter efterfrågar exakt de fält de behöver.
- Era controllers tillhandahåller data för varje fält.
Enligt konventionen hittar Spring Boot automatiskt filer med ändelserna .graphqls / .graphql under src/main/resources/graphql/.
Definiera objekttyper i SDL
En GraphQL-objekttyp beskriver formen på en entitet. Varje fält har ett namn och en typ.
ID,String,Int,Float,Booleanär de inbyggda skalärtyperna.- Ett avslutande
!markerar ett fält som icke-null. [Type]betecknar en lista.
Placera detta i src/main/resources/graphql/schema.graphqls.
type Book {
id: ID!
title: String!
pageCount: Int
author: Author!
}
type Author {
id: ID!
name: String!
books: [Book!]!
}Rott typen för Query
Alla läsoperationer finns under den särskilda rot typen Query. Varje fält i Query är en startpunkt som en klient kan anropa.
- Fält kan ta emot argument, till exempel
bookById(id: ID!). - Returtypen kan vara ett enskilt objekt, en lista eller en skalär.
En nullbar returtyp (utan !) är lämplig när entiteten kanske inte finns.
type Query {
bookById(id: ID!): Book
allBooks: [Book!]!
searchBooks(titleContains: String!): [Book!]!
}Mappa en Query till en controller
Spring for GraphQL mappar schemafält till Java-metoder med hjälp av annoterade controllers. En klass som är annoterad med @Controller exponerar handler-metoder med @QueryMapping.
- Metodnamnet måste matcha schemafältet, eller så anger Ni
@QueryMapping("fieldName"). - Argument binds med
@Argument.
Detta är ramverkskod (den kräver Spring-runtime), så den kan inte köras fristående.
@Controller
public class BookController {
private final BookRepository books;
public BookController(BookRepository books) {
this.books = books;
}
@QueryMapping
public Book bookById(@Argument String id) {
return books.findById(id).orElse(null);
}
@QueryMapping
public List<Book> allBooks() {
return books.findAll();
}
}Typmappning: SDL till Java
Spring mappar GraphQL-typer till Java-typer efter fältnamn, inte efter arv. Er POJO (record eller klass) behöver bara ha matchande accessorer.
- SDL
String→ JavaString - SDL
Int→ Javaint/Integer - SDL
ID→ vanligtvisString(ellerLongefter typkonvertering) - SDL
[Book!]!→List<Book>
Ett Java-record är den tydligaste representationen av en GraphQL-objekttyp.
public record Book(
String id,
String title,
Integer pageCount,
String authorId
) {}
public record Author(
String id,
String name
) {}Detaljer om argumentbindning
Annoteringen @Argument binder ett namngivet schemaargument till en metodparameter.
- Som standard måste parameternamnet matcha argumentnamnet (kompilering med
-parameterskrävs, vilket är aktiverat som standard i Spring Boot). - Åsidosätt detta explicit med
@Argument("titleContains"). - Komplexa input-typer binds automatiskt till ett Java-record eller en Java-klass.
Spring konverterar det inkommande GraphQL-värdet till parameterns Java-typ.
@QueryMapping
public List<Book> searchBooks(@Argument("titleContains") String fragment) {
return books.findAll().stream()
.filter(b -> b.title().toLowerCase().contains(fragment.toLowerCase()))
.toList();
}Lös kapslade fält med @SchemaMapping
När ett fält kräver mer arbete än en enkel getter (till exempel när Book.author måste slås upp) använder Ni @SchemaMapping. Källobjektet skickas in som en parameter.
- Metodens klass/typ härleds från parametertypen, eller anges med
@SchemaMapping(typeName = "Book"). - Detta löser N+1-problemet genom att Ni senare kan batcha med
@BatchMapping.
Här löser varje Book sitt author-fält vid behov.
@SchemaMapping
public Author author(Book book) {
return authorRepository.findById(book.authorId())
.orElseThrow(() -> new IllegalStateException("Author missing"));
}Definiera mutationer i SDL
Skrivoperationer finns under rottypen Mutation. De tar vanligtvis emot ett input-objekt och returnerar den skapade eller uppdaterade entiteten.
- Använd en särskild
input-typ för argument — input-typer kan inte ha fält som refererar till objekttyper. - Genom att returnera den ändrade entiteten kan klienter hämta det aktuella tillståndet igen i en enda tur och retur.
input AddBookInput {
title: String!
pageCount: Int
authorId: ID!
}
type Mutation {
addBook(input: AddBookInput!): Book!
deleteBook(id: ID!): Boolean!
}Mappa en mutation till en controller
Mutationer mappas med @MutationMapping. En GraphQL-input-typ binds smidigt till ett Java-record via @Argument.
- Record-fältnamnen måste matcha SDL-inputfältens namn.
- Returnera entiteten för att uppfylla det icke-nullbara resultatet
Book!.
Detta är fortfarande ramverkskod — den kräver Springs GraphQL-runtime och kan därför inte köras fristående.
public record AddBookInput(String title, Integer pageCount, String authorId) {}
@MutationMapping
public Book addBook(@Argument AddBookInput input) {
Book created = new Book(
UUID.randomUUID().toString(),
input.title(),
input.pageCount(),
input.authorId()
);
return books.save(created);
}Ren typmappning i vanlig Java
Logiken som formar data bakom en resolver är vanlig Java — Ni kan resonera om den utan någon server. Nedan körs ett sökfilter (innehållet i searchBooks) som ett komplett fristående program.
- Detta motsvarar exakt vad Er
@QueryMapping-metod gör internt. - Ingen Spring, ingen schema-motor — bara typmappning och filtrering.
import java.util.List;
public class Main {
record Book(String id, String title, Integer pageCount) {}
static List<Book> searchBooks(List<Book> all, String fragment) {
return all.stream()
.filter(b -> b.title().toLowerCase().contains(fragment.toLowerCase()))
.toList();
}
public static void main(String[] args) {
List<Book> catalog = List.of(
new Book("1", "Spring in Action", 600),
new Book("2", "GraphQL Basics", 220),
new Book("3", "Effective Java", 412)
);
searchBooks(catalog, "graphql").forEach(b -> System.out.println(b.title()));
}
}Där schema och kod möts
Vid uppstart validerar Spring att varje schemafält kan tillgodoses. Om ett fält saknar både getter och @SchemaMapping kan Ni få ett fel om olöst fält vid frågetillfället.
- Egenskaper i Ert record löses automatiskt efter namn.
- Beräknade / hämtade fält behöver en explicit mappningsmetod.
- Använd gränssnittet GraphiQL (aktivera
spring.graphql.graphiql.enabled=true) för att utforska det aktiva schemat.
Att hålla SDL- och Java-fältnamnen synkroniserade är den centrala disciplinen i schema-first-design.
Snabbkontroll
Ni har schemafältet Book.author: Author!, men ett Book-record lagrar bara authorId och saknar egenskapen author. Vad är det korrekta schema-first-sättet att lösa det?
Sammanfattning
Ni mappade ett GraphQL-schema till Spring-controllers enligt schema-first:
- SDL-filer under
src/main/resources/graphql/definierar objekt-,input-,Query- ochMutation-typer. @QueryMappinghanterar läsningar,@MutationMappinghanterar skrivningar, och båda binder argument med@Argument.@SchemaMapping(och@BatchMapping) löser kapslade/beräknade fält från ett källobjekt.- Typer mappas efter fältnamn: records är den tydligaste representationen, och SDL:s skalärer mappas till sina naturliga Java-typer.
Håll SDL- och Java-namnen synkroniserade, så förblir schemat den enda källan till sanning.
Lär dig Java med en AI-lärare – gratis
Skriv och kör riktig kod i webbläsaren, få omedelbar hjälp av en AI-lärare dygnet runt och fortsätt där du slutade – på webben eller i appen.
- Kurser
- 21
- Lektioner
- 84
Vanliga frågor
Är lektionen ”Schema-first-design och typmappning” gratis?
Ja – du kan läsa vilka 3 lektioner som helst i lärvägen Spring Boot 4 – komplett guide, inklusive ”Schema-first-design och typmappning”, kostnadsfritt i sin helhet här på webben. Därefter låser CoddyKit PRO upp alla lektioner, plus interaktiv övning med en inbyggd kodredigerare och en AI-lärare dygnet runt. Kursen i Spring Boot 4 – komplett guide innehåller totalt 4 lektioner.
Vad lär jag mig i ”Schema-first-design och typmappning”?
Definiera ett GraphQL-schema och mappa typer, queries och mutationer till Java-controller-metoder. Ni övar på Spring Boot 4 – komplett guide med praktisk kod som körs direkt i webbläsaren, medan en AI-handledare som är tillgänglig dygnet runt svarar på Era frågor under lektionen.
Behöver jag någon erfarenhet för att börja lära mig Spring Boot 4 – komplett guide?
Du behöver inga förkunskaper. Utbildningen i Spring Boot 4 – komplett guide på CoddyKit är upplagd för allt från nybörjare till avancerade elever, så att du kan börja här eller från början och gå fram i din egen takt. Detta är lektion 1 av 4.
Hur lång tid tar lektionen ”Schema-first-design och typmappning”?
De flesta CoddyKit-lektioner tar cirka 5–10 minuter. Varje lektion är kort och interaktiv, så att du gör stadiga framsteg och kan fortsätta precis där du slutade – på webben eller i appen.
Kan jag skriva och köra kod i den här Spring Boot 4 – komplett guide-lektionen?
Ja. Varje Spring Boot 4 – komplett guide-lektion innehåller en inbyggd kodredigerare, så att du kan skriva och köra riktig kod direkt i webbläsaren och få omedelbar AI-feedback – utan lokal installation.
Alla lektioner i den här kursen
- Schema-first-design och typmappning
- Data fetchers och argumentbindning
- Lös N+1 med batch loaders
- Prenumerationer, fel och schemasäkerhet