Skip to content

Commit 5daaf34

Browse files
wynnteoWynn Teo
andauthored
BAEL-8999 (#18651)
Co-authored-by: Wynn Teo <[email protected]>
1 parent 748fff9 commit 5daaf34

File tree

11 files changed

+455
-0
lines changed

11 files changed

+455
-0
lines changed
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
package com.baeldung.pagination;
2+
3+
4+
import org.springframework.boot.SpringApplication;
5+
import org.springframework.boot.autoconfigure.SpringBootApplication;
6+
7+
@SpringBootApplication
8+
public class GraphqlPagination {
9+
public static void main(String[] args) {
10+
SpringApplication.run(GraphqlPagination.class, args);
11+
}
12+
}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
package com.baeldung.pagination.dto;
2+
3+
import lombok.Getter;
4+
5+
import java.util.List;
6+
7+
@Getter
8+
public class BookConnection {
9+
private final List<BookEdge> edges;
10+
private final PageInfo pageInfo;
11+
12+
public BookConnection(List<BookEdge> edges, PageInfo pageInfo) {
13+
this.edges = edges;
14+
this.pageInfo = pageInfo;
15+
}
16+
}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
package com.baeldung.pagination.dto;
2+
3+
import com.baeldung.pagination.entity.Book;
4+
5+
import lombok.Getter;
6+
7+
@Getter
8+
public class BookEdge {
9+
private final Book node;
10+
private final String cursor;
11+
12+
public BookEdge(Book node, String cursor) {
13+
this.node = node;
14+
this.cursor = cursor;
15+
}
16+
}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
package com.baeldung.pagination.dto;
2+
3+
import lombok.Getter;
4+
import org.springframework.data.domain.Page;
5+
6+
import java.util.List;
7+
8+
import com.baeldung.pagination.entity.Book;
9+
10+
@Getter
11+
public class BookPage {
12+
private final List<Book> content;
13+
private final int totalPages;
14+
private final long totalElements;
15+
private final int number;
16+
private final int size;
17+
18+
public BookPage(Page<Book> page) {
19+
this.content = page.getContent();
20+
this.totalPages = page.getTotalPages();
21+
this.totalElements = page.getTotalElements();
22+
this.number = page.getNumber();
23+
this.size = page.getSize();
24+
}
25+
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
package com.baeldung.pagination.dto;
2+
3+
import lombok.Getter;
4+
5+
@Getter
6+
public class PageInfo {
7+
private final boolean hasNextPage;
8+
private final String endCursor;
9+
10+
public PageInfo(boolean hasNextPage, String endCursor) {
11+
this.hasNextPage = hasNextPage;
12+
this.endCursor = endCursor;
13+
}
14+
}
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
package com.baeldung.pagination.entity;
2+
3+
import jakarta.persistence.Entity;
4+
import jakarta.persistence.GeneratedValue;
5+
import jakarta.persistence.GenerationType;
6+
import jakarta.persistence.Id;
7+
import lombok.Getter;
8+
import lombok.Setter;
9+
10+
@Entity
11+
public class Book {
12+
@Id
13+
@GeneratedValue(strategy = GenerationType.IDENTITY)
14+
private Long id;
15+
16+
private String title;
17+
private String author;
18+
19+
public Long getId() {
20+
return this.id;
21+
}
22+
23+
public String getTitle() {
24+
return this.title;
25+
}
26+
27+
public String getAuthor() {
28+
return this.author;
29+
}
30+
31+
public void setId(Long id) {
32+
this.id = id;
33+
}
34+
35+
public void setTitle(String title) {
36+
this.title = title;
37+
}
38+
39+
public void setAuthor(String author) {
40+
this.author = author;
41+
}
42+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
package com.baeldung.pagination.repository;
2+
3+
import org.springframework.data.repository.CrudRepository;
4+
import org.springframework.data.repository.PagingAndSortingRepository;
5+
import org.springframework.stereotype.Repository;
6+
7+
import java.util.List;
8+
9+
import com.baeldung.pagination.entity.Book;
10+
11+
@Repository
12+
public interface BookRepository extends PagingAndSortingRepository<Book, Long>, CrudRepository<Book, Long> {
13+
List<Book> findByIdGreaterThanOrderByIdAsc(Long cursor, org.springframework.data.domain.Pageable pageable);
14+
List<Book> findAllByOrderByIdAsc(org.springframework.data.domain.Pageable pageable);
15+
boolean existsByIdGreaterThan(Long id);
16+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
package com.baeldung.pagination.resolver;
2+
3+
import org.springframework.data.domain.Page;
4+
import org.springframework.data.domain.PageRequest;
5+
import org.springframework.data.domain.Pageable;
6+
import org.springframework.graphql.data.method.annotation.Argument;
7+
import org.springframework.graphql.data.method.annotation.QueryMapping;
8+
import org.springframework.stereotype.Controller;
9+
10+
import java.util.List;
11+
import java.util.Optional;
12+
import java.util.stream.Collectors;
13+
14+
import com.baeldung.pagination.dto.BookConnection;
15+
import com.baeldung.pagination.dto.BookEdge;
16+
import com.baeldung.pagination.dto.BookPage;
17+
import com.baeldung.pagination.dto.PageInfo;
18+
import com.baeldung.pagination.entity.Book;
19+
import com.baeldung.pagination.repository.BookRepository;
20+
21+
@Controller
22+
public class BookQueryResolver {
23+
private final BookRepository bookRepository;
24+
25+
public BookQueryResolver(BookRepository bookRepository) {
26+
this.bookRepository = bookRepository;
27+
}
28+
29+
@QueryMapping
30+
public BookPage books(@Argument int page, @Argument int size) {
31+
Pageable pageable = PageRequest.of(page, size);
32+
Page<Book> bookPage = bookRepository.findAll(pageable);
33+
return new BookPage(bookPage);
34+
}
35+
36+
@QueryMapping
37+
public BookConnection booksByCursor(@Argument Optional<Long> cursor, @Argument int limit) {
38+
List<Book> books;
39+
40+
if (cursor.isPresent()) {
41+
books = bookRepository.findByIdGreaterThanOrderByIdAsc(cursor.get(), PageRequest.of(0, limit));
42+
} else {
43+
books = bookRepository.findAllByOrderByIdAsc(PageRequest.of(0, limit));
44+
}
45+
46+
List<BookEdge> edges = books.stream()
47+
.map(book -> new BookEdge(book, book.getId().toString()))
48+
.collect(Collectors.toList());
49+
String endCursor = books.isEmpty() ? null : books.get(books.size() - 1).getId().toString();
50+
boolean hasNextPage = !books.isEmpty() && bookRepository.existsByIdGreaterThan(books.get(books.size() - 1).getId());
51+
52+
PageInfo pageInfo = new PageInfo(hasNextPage, endCursor);
53+
54+
return new BookConnection(edges, pageInfo);
55+
}
56+
}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
spring:
2+
datasource:
3+
url: jdbc:h2:mem:testdb # H2 in-memory DB
4+
username: sa
5+
password: password
6+
driver-class-name: org.h2.Driver
7+
h2:
8+
console:
9+
enabled: true
10+
path: /h2-console
11+
jpa:
12+
hibernate:
13+
ddl-auto: update
14+
show-sql: false
15+
properties:
16+
hibernate.format_sql: true
17+
18+
graphql:
19+
servlet:
20+
enabled: true
21+
path: /graphql
22+
schema:
23+
locations: classpath:pagination/
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
type Book {
2+
id: ID!
3+
title: String
4+
author: String
5+
}
6+
7+
type BookPage {
8+
content: [Book]
9+
totalPages: Int
10+
totalElements: Int
11+
number: Int
12+
size: Int
13+
}
14+
15+
type BookEdge {
16+
node: Book
17+
cursor: String
18+
}
19+
20+
type PageInfo {
21+
hasNextPage: Boolean
22+
endCursor: String
23+
}
24+
25+
type BookConnection {
26+
edges: [BookEdge]
27+
pageInfo: PageInfo
28+
}
29+
30+
type Query {
31+
books(page: Int, size: Int): BookPage
32+
booksByCursor(cursor: ID, limit: Int!): BookConnection
33+
}

0 commit comments

Comments
 (0)