Scroll API Implementation (#14435)
Co-authored-by: technoddy <mail.technoddy@gmail.com>
This commit is contained in:
parent
787ed13597
commit
aae5f7dc38
|
@ -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>
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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 + '\'' + '}';
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,4 @@
|
|||
|
||||
logging.level.org.hibernate:
|
||||
SQL: DEBUG
|
||||
type.descriptor.sql.BasicBinder: TRACE
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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
|
Loading…
Reference in New Issue