Implementering av bunting og hurtigbufring
Integrer DataLoaders i Spring Boot-resolverne dine for å optimalisere datahenting og redusere antallet rundturer til databasen.
Implementering av bunting og hurtigbufring er en gratis leksjon i GraphQL-API-er med Spring Boot på CoddyKit. Dette er leksjon 3 av 4. Du kan lese hele leksjonen gratis nedenfor – og deretter øve praktisk i nettleseren med en innebygd kodeeditor og en AI-veileder som er tilgjengelig døgnet rundt. Den er en del av læringsløpet i GraphQL-API-er med Spring Boot, og fremdriften din synkroniseres mellom nettet og CoddyKit-appen. Kurset i GraphQL-API-er med Spring Boot inneholder totalt 4 leksjoner.
DataLoaders: På tide å implementere!
Velkommen tilbake! I tidligere leksjoner lærte vi om N+1-problemet og hvordan DataLoaders gir en elegant løsning gjennom samling i grupper og bufring.
I dag skal vi arbeide praktisk og integrere DataLoaders i en Spring Boot GraphQL-applikasjon. Vi skal se hvordan en BatchLoader defineres og registreres, og hvordan den brukes i GraphQL-resolverne.
Simulere en datatjeneste
Først setter vi opp en enkel mock-tjeneste som simulerer henting av brukere fra en database. Denne tjenesten vil bli kalt av DataLoaders.
Legg merke til System.out.println, som hjelper oss med å se når det faktiske «databasekallet» skjer, og som senere demonstrerer samling i grupper.
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
// A simple User data class
class User {
String id;
String name;
User(String id, String name) {
this.id = id; this.name = name;
}
public String getId() { return id; }
public String getName() { return name; }
}
// Mock service to fetch users (simulates DB call)
class MockUserService {
private final Map<String, User> users = Map.of(
"1", new User("1", "Alice"),
"2", new User("2", "Bob"),
"3", new User("3", "Charlie"),
"4", new User("4", "David")
);
public List<User> findAllByIds(List<String> ids) {
System.out.println("DB Call: Fetching users for IDs: " + ids);
return ids.stream()
.map(users::get)
.filter(user -> user != null)
.collect(Collectors.toList());
}
}
public class Main {
public static void main(String[] args) {
MockUserService service = new MockUserService();
List<User> foundUsers = service.findAllByIds(List.of("1", "3"));
System.out.println("Found: " + foundUsers.size() + " users.");
}
}BatchLoader-grensesnittet
Kjernen i DataLoaders mekanisme for samling i grupper er grensesnittet BatchLoader. Det definerer én metode: load(List<K> keys).
- Den tar imot en liste med nøkler (for eksempel bruker-ID-er).
- Den returnerer en
CompletionStage(et fremtidig resultat) med en liste over verdier (for eksempel brukere). - Det avgjørende er at denne metoden kalles én gang for alle nøkler som etterspørres i løpet av et kort tidsvindu. Dermed kan de hentes i én optimalisert operasjon, for eksempel én databaseforespørsel.
Implementere Deres BatchLoader
Nå oppretter vi UserBatchLoader. Den implementerer grensesnittet BatchLoader<String, User>, noe som betyr at den tar imot en String (bruker-ID) som nøkkel og returnerer et User-objekt.
Den bruker MockUserService til å utføre selve batch-hentingen.
import org.dataloader.BatchLoader;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CompletionStage;
// (Assume User and MockUserService are defined elsewhere)
// For runnable example, they would be in the same file.
public class UserBatchLoader implements BatchLoader<String, User> {
private final MockUserService userService;
public UserBatchLoader(MockUserService userService) {
this.userService = userService;
}
@Override
public CompletionStage<List<User>> load(List<String> userIds) {
// This method is called once with all requested IDs.
// We delegate to our mock service to fetch them in one go.
return CompletableFuture.supplyAsync(
() -> userService.findAllByIds(userIds)
);
}
}
public class Main {
public static void main(String[] args) {
MockUserService userService = new MockUserService();
UserBatchLoader batchLoader = new UserBatchLoader(userService);
System.out.println("UserBatchLoader created!");
}
}DataLoaderRegistry
I en Spring Boot GraphQL-applikasjon administreres DataLoader-instanser i en DataLoaderRegistry. Dette registeret fungerer som en beholder for alle DataLoaders som er tilgjengelige mens en GraphQL-forespørsel kjøres.
- Hver DataLoader registreres med et unikt navn (for eksempel «userDataLoader»).
- Resolverne henter den nødvendige DataLoader-en fra dette registeret ved hjelp av navnet.
- Spring for GraphQL håndterer vanligvis livssyklusen og omfanget til dette registeret per forespørsel.
Konfigurere DataLoaders
Slik oppretter De en DataLoader-instans fra Deres BatchLoader og registrerer den i en DataLoaderRegistry. Dette oppsettet er avgjørende for å gjøre DataLoaders tilgjengelige for resolverne.
import org.dataloader.DataLoader;
import org.dataloader.DataLoaderRegistry;
// (Assume User, MockUserService, UserBatchLoader are defined)
public class Main {
public static void main(String[] args) {
MockUserService userService = new MockUserService();
UserBatchLoader userBatchLoader = new UserBatchLoader(userService);
// Create a DataLoader instance
DataLoader<String, User> userDataLoader =
DataLoader.newDataLoader(userBatchLoader);
// Register it in a DataLoaderRegistry
DataLoaderRegistry registry = new DataLoaderRegistry();
registry.register("userDataLoader", userDataLoader);
System.out.println("DataLoader registered as 'userDataLoader'!");
// In a real app, this registry would be part of the GraphQLContext.
// Resolvers would then retrieve DataLoaders from it.
}
}Bruke DataLoader i resolverne
Når DataLoader-en er registrert, kan De bruke den i GraphQL-resolverne. I stedet for å kalle tjenesten direkte kaller De dataLoader.load(id).
- Metoden
load()returnerer enCompletionStage, ikke selve objektet. - DataLoader samler alle
load()-kall i den gjeldende kjøringsrammen før den sender dem videre tilBatchLoader. - Spring for GraphQL sender automatisk DataLoaders videre på slutten av en datahentingssyklus.
Resolver-integrasjon i praksis
Dette eksempelet simulerer en GraphQL-forespørsel der flere bruker-ID-er etterspørres. Følg med på meldingen «DB Call» i resultatet for å se hvordan DataLoaders samler disse forespørslene i én enkelt operasjon, selv om de ser separate ut i resolver-logikken.
import org.dataloader.DataLoader;
import org.dataloader.DataLoaderRegistry;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CompletionStage;
import java.util.stream.Collectors;
// User, MockUserService, UserBatchLoader definitions (from previous scenes)
class User {
String id; String name;
User(String id, String name) { this.id = id; this.name = name; }
public String getId() { return id; }
public String getName() { return name; }
}
class MockUserService {
private final Map<String, User> users = Map.of(
"1", new User("1", "Alice"), "2", new User("2", "Bob"),
"3", new User("3", "Charlie"), "4", new User("4", "David")
);
public List<User> findAllByIds(List<String> ids) {
System.out.println("DB Call: Fetching users for IDs: " + ids);
return ids.stream().map(users::get)
.filter(user -> user != null).collect(Collectors.toList());
}
}
class UserBatchLoader implements BatchLoader<String, User> {
private final MockUserService userService;
public UserBatchLoader(MockUserService userService) { this.userService = userService; }
@Override
public CompletionStage<List<User>> load(List<String> userIds) {
return CompletableFuture.supplyAsync(() -> userService.findAllByIds(userIds));
}
}
// Simulate a GraphQL Query Resolver method
public class UserResolver {
private final DataLoaderRegistry dataLoaderRegistry;
public UserResolver(DataLoaderRegistry registry) {
this.dataLoaderRegistry = registry;
}
public CompletionStage<User> getUserById(String id) {
DataLoader<String, User> userDataLoader =
dataLoaderRegistry.getDataLoader("userDataLoader");
return userDataLoader.load(id);
}
public static void main(String[] args) {
MockUserService userService = new MockUserService();
UserBatchLoader userBatchLoader = new UserBatchLoader(userService);
DataLoader<String, User> userDataLoader =
DataLoader.newDataLoader(userBatchLoader);
DataLoaderRegistry registry = new DataLoaderRegistry();
registry.register("userDataLoader", userDataLoader);
UserResolver resolver = new UserResolver(registry);
System.out.println("Requesting User 1 and User 2 concurrently...");
// Simulate two concurrent GraphQL field fetches
CompletableFuture<User> user1Future =
(CompletableFuture<User>) resolver.getUserById("1");
CompletableFuture<User> user2Future =
(CompletableFuture<User>) resolver.getUserById("2");
CompletableFuture.allOf(user1Future, user2Future)
.thenRun(() -> {
try {
System.out.println("Fetched User 1: " + user1Future.join().getName());
System.out.println("Fetched User 2: " + user2Future.join().getName());
} catch (Exception e) {
e.printStackTrace();
}
// For this manual demo, we dispatch the DataLoader.
// In Spring GraphQL, this is handled automatically.
userDataLoader.dispatch();
}).join();
}
}DataLoaders innebygde bufring
I tillegg til samling i grupper tilbyr DataLoaders også bufring per forespørsel direkte. Det betyr følgende:
- Hvis
dataLoader.load("1")kalles flere ganger i løpet av den samme GraphQL-forespørselen, blirBatchLoader-ens hente-funksjon for ID «1» bare kalt én gang. - Senere kall for samme ID i løpet av denne forespørselen returnerer resultatet som allerede er hentet og bufret.
- Dette forhindrer overflødige databasekall for de samme dataene i én GraphQL-operasjon og gir ytterligere bedre ytelse.
Kontroller forståelsen Deres
De har lært hvordan DataLoaders implementeres for samling i grupper og bufring. La oss teste kunnskapene Deres!
Oppsummering: Samling og bufring
Godt jobbet! De har nå lært hvordan DataLoaders implementeres i Spring Boot GraphQL.
- Vi opprettet en
MockUserServicefor å simulere datahenting. - Vi bygde en
UserBatchLoaderfor å håndtere samling av flere ID-forespørsler. - Vi så hvordan
DataLoader-instanser initialiseres og registreres i enDataLoaderRegistry. - Til slutt integrerte vi DataLoaders i en resolver og så hvordan forespørsler samles, og hvordan bufring forhindrer overflødige kall.
Ved å bruke DataLoaders optimaliserer De ytelsen til GraphQL API-et betydelig, særlig ved arbeid med komplekse datagrafer og nestede objekter.
Lær deg GraphQL-API-er med Spring Boot med en AI-veileder – gratis
Skriv og kjør ekte kode i nettleseren, få umiddelbar hjelp fra en AI-veileder som er tilgjengelig døgnet rundt, og fortsett der du slapp – på nettet eller i appen.
- Kurs
- 12
- Leksjoner
- 48
Ofte stilte spørsmål
Er leksjonen «Implementering av bunting og hurtigbufring» gratis?
Ja – hele teksten i «Implementering av bunting og hurtigbufring» er gratis å lese her på nettet. For å øve interaktivt med en innebygd kodeeditor og en AI-veileder som er tilgjengelig døgnet rundt, og for å låse opp resten av GraphQL-API-er med Spring Boot-kurset, kan du oppgradere til CoddyKit PRO. Kurset i GraphQL-API-er med Spring Boot inneholder totalt 4 leksjoner.
Hva lærer jeg i «Implementering av bunting og hurtigbufring»?
Integrer DataLoaders i Spring Boot-resolverne dine for å optimalisere datahenting og redusere antallet rundturer til databasen. Du øver på GraphQL-API-er med Spring Boot med praktisk kode som du kjører direkte i nettleseren, mens en AI-veileder som er tilgjengelig døgnet rundt, svarer på spørsmålene dine mens du jobber deg gjennom leksjonen.
Trenger jeg erfaring for å begynne med GraphQL-API-er med Spring Boot?
Ingen tidligere erfaring er nødvendig. GraphQL-API-er med Spring Boot på CoddyKit er lagt opp for både nybegynnere og viderekomne, så De kan begynne her eller helt fra start og lære i Deres eget tempo. Dette er leksjon 3 av 4.
Hvor lang tid tar leksjonen «Implementering av bunting og hurtigbufring»?
De fleste CoddyKit-leksjoner tar omtrent 5–10 minutter. Hver leksjon er kort og interaktiv, slik at De gjør jevne fremskritt og kan fortsette akkurat der De slapp – både på nettet og i appen.
Kan jeg skrive og kjøre kode i denne GraphQL-API-er med Spring Boot-leksjonen?
Ja. Alle GraphQL-API-er med Spring Boot-leksjoner har en innebygd kodeeditor, slik at De kan skrive og kjøre ekte kode direkte i nettleseren og få umiddelbar tilbakemelding fra AI – uten lokal konfigurering.
Alle leksjonene i dette kurset
- N+1-problemet forklart
- Introduksjon til GraphQL DataLoaders
- Implementering av bunting og hurtigbufring
- DataLoaders med Spring Context og asynkronitet