Last active
August 24, 2024 12:00
-
-
Save josergdev/2d70f4975cd33140e1b9659ccc426917 to your computer and use it in GitHub Desktop.
SimpleJpaRepository extension to find All Slice by Specification
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package dev.joserg.jpa; | |
import jakarta.persistence.EntityManager; | |
import org.jetbrains.annotations.Nullable; | |
import org.springframework.data.domain.Pageable; | |
import org.springframework.data.domain.Slice; | |
import org.springframework.data.domain.SliceImpl; | |
import org.springframework.data.jpa.domain.Specification; | |
import org.springframework.data.jpa.repository.support.JpaEntityInformation; | |
import org.springframework.data.jpa.repository.support.SimpleJpaRepository; | |
public class SliceJpaRepositoryImpl<T, I> extends SimpleJpaRepository<T, I> { | |
public BaseJpaRepositoryImpl(final JpaEntityInformation<T, ?> entityInformation, final EntityManager entityManager) { | |
super(entityInformation, entityManager); | |
} | |
@Override | |
public Slice<T> findAllSliced(@Nullable final Specification<T> spec, final Pageable pageable) { | |
final var query = this.getQuery(spec, pageable.getSort()); | |
query.setFirstResult((int) pageable.getOffset()); | |
final var extraSize = pageable.getPageSize() + 1; | |
query.setMaxResults(extraSize); | |
final var result = query.getResultList(); | |
final var hasNext = result.size() == extraSize; | |
if (hasNext) { | |
result.remove(extraSize - 1); | |
} | |
return new SliceImpl<>(result, pageable, hasNext); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package dev.joserg.jpa; | |
import static org.assertj.core.api.Assertions.assertThat; | |
import static org.mockito.Mockito.mock; | |
import static org.mockito.Mockito.when; | |
import java.util.ArrayList; | |
import java.util.List; | |
import java.util.UUID; | |
import jakarta.persistence.EntityManager; | |
import jakarta.persistence.TypedQuery; | |
import jakarta.persistence.criteria.CriteriaBuilder; | |
import jakarta.persistence.criteria.CriteriaQuery; | |
import org.junit.jupiter.api.BeforeEach; | |
import org.junit.jupiter.api.Test; | |
import org.junit.jupiter.api.extension.ExtendWith; | |
import org.mockito.Mock; | |
import org.mockito.junit.jupiter.MockitoExtension; | |
import org.springframework.data.domain.PageRequest; | |
import org.springframework.data.domain.SliceImpl; | |
import org.springframework.data.jpa.domain.Specification; | |
import org.springframework.data.jpa.repository.support.CrudMethodMetadata; | |
import org.springframework.data.jpa.repository.support.JpaEntityInformation; | |
import org.springframework.data.jpa.repository.support.MutableQueryHints; | |
@ExtendWith(MockitoExtension.class) | |
class SliceJpaRepositoryImplTest { | |
private SliceJpaRepositoryImpl<ExampleEntity, Integer> repo; | |
@Mock | |
EntityManager em; | |
@Mock | |
CriteriaBuilder builder; | |
@Mock | |
CriteriaQuery<ExampleEntity> criteriaQuery; | |
@Mock | |
TypedQuery<ExampleEntity> query; | |
@Mock | |
JpaEntityInformation<ExampleEntity, UUID> information; | |
@Mock | |
CrudMethodMetadata metadata; | |
@BeforeEach | |
void setUp() { | |
when(this.em.getDelegate()).thenReturn(this.em); | |
when(this.information.getJavaType()).thenReturn(ExampleEntity.class); | |
when(this.em.getCriteriaBuilder()).thenReturn(this.builder); | |
when(this.builder.createQuery(ExampleEntity.class)).thenReturn(this.criteriaQuery); | |
when(this.em.createQuery(this.criteriaQuery)).thenReturn(this.query); | |
when(this.metadata.getQueryHints()).thenReturn(new MutableQueryHints()); | |
this.repo = new BaseJpaRepositoryImpl<>(this.information, this.em); | |
this.repo.setRepositoryMethodMetadata(this.metadata); | |
} | |
@Test | |
void should_find_all_sliced_that_has_next() { | |
final var pageRequest = PageRequest.of(0, 1); | |
final var resultList = new ArrayList<>(List.of(mock(ExampleEntity.class), mock(ExampleEntity.class))); | |
when(this.query.getResultList()).thenReturn(resultList); | |
final var actual = this.repo.findAllSliced(Specification.where(null), pageRequest); | |
final var expected = new SliceImpl<>(resultList, pageRequest, true); | |
assertThat(actual.getContent()).hasSize(1); | |
assertThat(actual).usingRecursiveComparison().isEqualTo(expected); | |
} | |
@Test | |
void should_find_all_sliced_that_has_not_next() { | |
final var pageRequest = PageRequest.of(0, 2); | |
final var resultList = new ArrayList<>(List.of(mock(ExampleEntity.class), mock(ExampleEntity.class))); | |
when(this.query.getResultList()).thenReturn(resultList); | |
final var actual = this.repo.findAllSliced(Specification.where(null), pageRequest); | |
final var expected = new SliceImpl<>(resultList, pageRequest, false); | |
assertThat(actual.getContent()).hasSize(2); | |
assertThat(actual).usingRecursiveComparison().isEqualTo(expected); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment