diff --git a/spring-batch-2/pom.xml b/spring-batch-2/pom.xml
index 8205853108e3..a04baab9e442 100644
--- a/spring-batch-2/pom.xml
+++ b/spring-batch-2/pom.xml
@@ -104,6 +104,11 @@
+
+ com.graphql-java
+ java-dataloader
+ ${java-dataloader.version}
+
@@ -123,6 +128,7 @@
5.2.0
4.2.1
3.24.2
+ 3.2.0
com.baeldung.batch.SpringBootBatchProcessingApplication
diff --git a/spring-batch-2/src/main/java/com/baeldung/dataloaderbatchprocessing/DataLoaderApp.java b/spring-batch-2/src/main/java/com/baeldung/dataloaderbatchprocessing/DataLoaderApp.java
new file mode 100644
index 000000000000..2228c6b9a4e8
--- /dev/null
+++ b/spring-batch-2/src/main/java/com/baeldung/dataloaderbatchprocessing/DataLoaderApp.java
@@ -0,0 +1,13 @@
+package com.baeldung.dataloaderbatchprocessing;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+
+@SpringBootApplication
+public class DataLoaderApp {
+
+ public static void main(String[] args) {
+ SpringApplication.run(DataLoaderApp.class, args);
+ }
+}
+
diff --git a/spring-batch-2/src/main/java/com/baeldung/dataloaderbatchprocessing/UserDataLoader.java b/spring-batch-2/src/main/java/com/baeldung/dataloaderbatchprocessing/UserDataLoader.java
new file mode 100644
index 000000000000..0f56bc3e443c
--- /dev/null
+++ b/spring-batch-2/src/main/java/com/baeldung/dataloaderbatchprocessing/UserDataLoader.java
@@ -0,0 +1,37 @@
+package com.baeldung.dataloaderbatchprocessing;
+
+import org.dataloader.BatchLoader;
+import org.dataloader.DataLoader;
+import org.dataloader.DataLoaderFactory;
+import org.springframework.stereotype.Component;
+
+import java.util.Map;
+import java.util.stream.Collectors;
+
+import com.baeldung.dataloaderbatchprocessing.entity.User;
+import com.baeldung.dataloaderbatchprocessing.service.UserService;
+
+@Component
+public class UserDataLoader {
+
+ private final UserService userService;
+
+ public UserDataLoader(UserService userService) {
+ this.userService = userService;
+ }
+
+ public DataLoader createUserLoader() {
+ BatchLoader userBatchLoader = ids -> {
+ return userService.getUsersByIds(ids)
+ .thenApply(users -> {
+ Map userMap = users.stream()
+ .collect(Collectors.toMap(User::getId, user -> user));
+ return ids.stream()
+ .map(userMap::get)
+ .collect(Collectors.toList());
+ });
+ };
+
+ return DataLoaderFactory.newDataLoader(userBatchLoader);
+ }
+}
diff --git a/spring-batch-2/src/main/java/com/baeldung/dataloaderbatchprocessing/entity/User.java b/spring-batch-2/src/main/java/com/baeldung/dataloaderbatchprocessing/entity/User.java
new file mode 100644
index 000000000000..9c030140d748
--- /dev/null
+++ b/spring-batch-2/src/main/java/com/baeldung/dataloaderbatchprocessing/entity/User.java
@@ -0,0 +1,21 @@
+package com.baeldung.dataloaderbatchprocessing.entity;
+
+import jakarta.persistence.Entity;
+import jakarta.persistence.Id;
+import jakarta.persistence.Table;
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+
+@Entity
+@Table(name = "users")
+@Getter
+@AllArgsConstructor
+@NoArgsConstructor
+public class User {
+
+ @Id
+ private String id;
+ private String name;
+}
+
diff --git a/spring-batch-2/src/main/java/com/baeldung/dataloaderbatchprocessing/repository/UserRepository.java b/spring-batch-2/src/main/java/com/baeldung/dataloaderbatchprocessing/repository/UserRepository.java
new file mode 100644
index 000000000000..2fcedde9478c
--- /dev/null
+++ b/spring-batch-2/src/main/java/com/baeldung/dataloaderbatchprocessing/repository/UserRepository.java
@@ -0,0 +1,9 @@
+package com.baeldung.dataloaderbatchprocessing.repository;
+
+import org.springframework.data.jpa.repository.JpaRepository;
+
+import com.baeldung.dataloaderbatchprocessing.entity.User;
+
+public interface UserRepository extends JpaRepository {
+}
+
diff --git a/spring-batch-2/src/main/java/com/baeldung/dataloaderbatchprocessing/service/UserService.java b/spring-batch-2/src/main/java/com/baeldung/dataloaderbatchprocessing/service/UserService.java
new file mode 100644
index 000000000000..3e258184c53e
--- /dev/null
+++ b/spring-batch-2/src/main/java/com/baeldung/dataloaderbatchprocessing/service/UserService.java
@@ -0,0 +1,22 @@
+package com.baeldung.dataloaderbatchprocessing.service;
+import org.springframework.stereotype.Service;
+
+import java.util.List;
+import java.util.concurrent.CompletableFuture;
+
+import com.baeldung.dataloaderbatchprocessing.entity.User;
+import com.baeldung.dataloaderbatchprocessing.repository.UserRepository;
+
+@Service
+public class UserService {
+ private final UserRepository userRepository;
+
+ public UserService(UserRepository userRepository) {
+ this.userRepository = userRepository;
+ }
+
+ public CompletableFuture> getUsersByIds(List ids) {
+ return CompletableFuture.supplyAsync(() -> userRepository.findAllById(ids));
+ }
+}
+
diff --git a/spring-batch-2/src/test/java/com/baeldung/dataloaderbatchprocessing/DataLoaderUnitTest.java b/spring-batch-2/src/test/java/com/baeldung/dataloaderbatchprocessing/DataLoaderUnitTest.java
new file mode 100644
index 000000000000..7a90ebf4d326
--- /dev/null
+++ b/spring-batch-2/src/test/java/com/baeldung/dataloaderbatchprocessing/DataLoaderUnitTest.java
@@ -0,0 +1,60 @@
+package com.baeldung.dataloaderbatchprocessing;
+
+import com.baeldung.dataloaderbatchprocessing.entity.User;
+import com.baeldung.dataloaderbatchprocessing.repository.UserRepository;
+import com.baeldung.dataloaderbatchprocessing.service.UserService;
+import org.dataloader.DataLoader;
+import org.dataloader.DataLoaderRegistry;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.boot.test.mock.mockito.SpyBean;
+
+import java.util.Arrays;
+import java.util.concurrent.CompletableFuture;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.Mockito.*;
+
+@SpringBootTest(classes = DataLoaderApp.class)
+class UserDataLoaderIntegrationTest {
+
+ @Autowired
+ private UserRepository userRepository;
+
+ @SpyBean
+ private UserService userService;
+
+ private DataLoader userDataLoader;
+
+ @BeforeEach
+ void setUp() {
+ userRepository.deleteAll();
+
+ User user1 = new User("101", "User_101");
+ User user2 = new User("102", "User_102");
+ User user3 = new User("103", "User_103");
+ userRepository.saveAll(Arrays.asList(user1, user2, user3));
+
+ userDataLoader = new DataLoader<>(userService::getUsersByIds);
+ DataLoaderRegistry registry = new DataLoaderRegistry();
+ registry.register("userDataLoader", userDataLoader);
+ }
+
+ @Test
+ void whenLoadingUsers_thenBatchLoaderIsInvokedAndResultsReturned() {
+ CompletableFuture userFuture1 = userDataLoader.load("101");
+ CompletableFuture userFuture2 = userDataLoader.load("102");
+ CompletableFuture userFuture3 = userDataLoader.load("103");
+
+ userDataLoader.dispatchAndJoin();
+
+ verify(userService, times(1)).getUsersByIds(anyList());
+
+ assertThat(userFuture1.join().getName()).isEqualTo("User_101");
+ assertThat(userFuture2.join().getName()).isEqualTo("User_102");
+ assertThat(userFuture3.join().getName()).isEqualTo("User_103");
+ }
+}
+