Scroll API Implementation (#14435)

Co-authored-by: technoddy <mail.technoddy@gmail.com>
This commit is contained in:
Sam 2023-07-27 06:00:54 -04:00 committed by GitHub
parent 787ed13597
commit aae5f7dc38
8 changed files with 278 additions and 0 deletions

View File

@ -0,0 +1,63 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.baeldung.boot.persistence</groupId>
<artifactId>spring-boot-persistence-4</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>spring-boot-persistence-4</name>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.junit</groupId>
<artifactId>junit-bom</artifactId>
<version>${junit-jupiter.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>${spring.boot.dependencies}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
<properties>
<spring.boot.dependencies>3.1.0</spring.boot.dependencies>
<junit-jupiter.version>5.9.3</junit-jupiter.version>
<maven.compiler.source>17</maven.compiler.source>
<maven.compiler.target>17</maven.compiler.target>
</properties>
</project>

View File

@ -0,0 +1,11 @@
package com.baeldung.scrollapi;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class ScrollAPIApplication {
public static void main(String[] args) {
SpringApplication.run(ScrollAPIApplication.class, args);
}
}

View File

@ -0,0 +1,53 @@
package com.baeldung.scrollapi.entity;
import jakarta.persistence.*;
@Entity
@Table(name = "BOOK_REVIEWS")
public class BookReview {
@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "book_reviews_reviews_id_seq")
@SequenceGenerator(name = "book_reviews_reviews_id_seq", sequenceName = "book_reviews_reviews_id_seq", allocationSize = 1)
private Long reviewsId;
private String userId;
private String isbn;
private String bookRating;
public Long getReviewsId() {
return reviewsId;
}
public void setReviewsId(Long reviewsId) {
this.reviewsId = reviewsId;
}
public String getUserId() {
return userId;
}
public void setUserId(String userId) {
this.userId = userId;
}
public String getIsbn() {
return isbn;
}
public void setIsbn(String isbn) {
this.isbn = isbn;
}
public String getBookRating() {
return bookRating;
}
public void setBookRating(String bookRating) {
this.bookRating = bookRating;
}
@Override
public String toString() {
return "BookReview{" + "reviewsId=" + reviewsId + ", userId='" + userId + '\'' + ", isbn='" + isbn + '\'' + ", bookRating='" + bookRating + '\'' + '}';
}
}

View File

@ -0,0 +1,16 @@
package com.baeldung.scrollapi.repository;
import org.springframework.data.domain.KeysetScrollPosition;
import org.springframework.data.domain.OffsetScrollPosition;
import org.springframework.data.domain.Window;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.repository.Repository;
import com.baeldung.scrollapi.entity.BookReview;
public interface BookRepository extends JpaRepository<BookReview, Long> {
Window<BookReview> findFirst5ByBookRating(String bookRating, OffsetScrollPosition position);
Window<BookReview> findFirst5ByBookRating(String bookRating, KeysetScrollPosition position);
}

View File

@ -0,0 +1,53 @@
package com.baeldung.scrollapi.service;
import java.util.ArrayList;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.KeysetScrollPosition;
import org.springframework.data.domain.OffsetScrollPosition;
import org.springframework.data.domain.ScrollPosition;
import org.springframework.data.domain.Window;
import org.springframework.data.support.WindowIterator;
import org.springframework.stereotype.Service;
import com.baeldung.scrollapi.entity.BookReview;
import com.baeldung.scrollapi.repository.BookRepository;
@Service
public class BookLogic {
@Autowired
private BookRepository bookRepository;
public List<BookReview> getBooksUsingOffset(String rating) {
OffsetScrollPosition offset = ScrollPosition.offset();
Window<BookReview> bookReviews = bookRepository.findFirst5ByBookRating(rating, offset);
List<BookReview> bookReviewsResult = new ArrayList<>();
do {
bookReviews.forEach(bookReviewsResult::add);
bookReviews = bookRepository.findFirst5ByBookRating(rating, (OffsetScrollPosition) bookReviews.positionAt(bookReviews.size() - 1));
} while (!bookReviews.isEmpty() && bookReviews.hasNext());
return bookReviewsResult;
}
public List<BookReview> getBooksUsingOffSetFilteringAndWindowIterator(String rating) {
WindowIterator<BookReview> bookReviews = WindowIterator.of(position -> bookRepository.findFirst5ByBookRating("3.5", (OffsetScrollPosition) position))
.startingAt(ScrollPosition.offset());
List<BookReview> bookReviewsResult = new ArrayList<>();
bookReviews.forEachRemaining(bookReviewsResult::add);
return bookReviewsResult;
}
public List<BookReview> getBooksUsingKeySetFiltering(String rating) {
WindowIterator<BookReview> bookReviews = WindowIterator.of(position -> bookRepository.findFirst5ByBookRating(rating, (KeysetScrollPosition) position))
.startingAt(ScrollPosition.keyset());
List<BookReview> bookReviewsResult = new ArrayList<>();
bookReviews.forEachRemaining(bookReviewsResult::add);
return bookReviewsResult;
}
}

View File

@ -0,0 +1,4 @@
logging.level.org.hibernate:
SQL: DEBUG
type.descriptor.sql.BasicBinder: TRACE

View File

@ -0,0 +1,73 @@
package com.baeldung.boot.scrollapi.service;
import static org.assertj.core.api.AssertionsForClassTypes.assertThat;
import java.util.List;
import java.util.UUID;
import java.util.stream.IntStream;
import org.junit.jupiter.api.AfterEach;
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 com.baeldung.scrollapi.ScrollAPIApplication;
import com.baeldung.scrollapi.entity.BookReview;
import com.baeldung.scrollapi.repository.BookRepository;
import com.baeldung.scrollapi.service.BookLogic;
@SpringBootTest(classes = ScrollAPIApplication.class)
class BookLogicUnitTest {
@Autowired
private BookRepository bookRepository;
@Autowired
private BookLogic bookLogic;
@BeforeEach
public void beforeEach() {
IntStream.rangeClosed(1, 5)
.forEach(i -> insertBookReview());
}
@AfterEach
public void afterEach() {
bookRepository.deleteAll();
}
@Test
public void givenBookReviewInTable_whenGetBooksUsingOffset_returnsBookReviews() {
List<BookReview> bookReviews = bookLogic.getBooksUsingOffset("3.5");
assertThat(bookReviews.size()).isEqualTo(5);
}
@Test
public void givenBookReviewInTable_whenGetBooksUsingOffSetFilteringAndWindowIterator_returnsBookReviews() {
List<BookReview> bookReviews = bookLogic.getBooksUsingOffSetFilteringAndWindowIterator("3.5");
assertThat(bookReviews.size()).isEqualTo(5);
}
@Test
public void givenBookReviewInTable_whenGetBooksUsingKeySetFiltering_returnsBookReviews() {
List<BookReview> bookReviews = bookLogic.getBooksUsingKeySetFiltering("3.5");
assertThat(bookReviews.size()).isEqualTo(5);
}
private void insertBookReview() {
BookReview bookReview = getBookReview();
bookRepository.save(bookReview);
}
private static BookReview getBookReview() {
BookReview bookReview = new BookReview();
String seed = UUID.randomUUID()
.toString();
bookReview.setIsbn("isbn" + seed);
bookReview.setBookRating("3.5");
bookReview.setUserId(seed);
return bookReview;
}
}

View File

@ -0,0 +1,5 @@
# spring.datasource.x
spring.datasource.driver-class-name=org.h2.Driver
spring.datasource.url=jdbc:h2:mem:db;DB_CLOSE_DELAY=-1
spring.datasource.username=sa
spring.datasource.password=sa