Skip to content

Commit

Permalink
feat(spring-jpa-pagination): QuerydslPredicateExecutor using
Browse files Browse the repository at this point in the history
  • Loading branch information
gmoon92 committed May 28, 2024
1 parent 3019663 commit 62c3027
Show file tree
Hide file tree
Showing 18 changed files with 140 additions and 66 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,11 @@

@Getter
@Setter
public abstract class Pageable implements Serializable {
public abstract class BasePageable implements Serializable {

private static final long serialVersionUID = -2648676657463697561L;

private static final Pageable UNPAGED = new UnpagedPageable();
private static final BasePageable UNPAGED = new UnpagedPageable();

public static final int DEFAULT_PAGE = 1;
public static final int DEFAULT_PAGE_SIZE = 15;
Expand All @@ -27,25 +27,25 @@ public abstract class Pageable implements Serializable {
private Integer page = 1;
private long offset = 0;

public Pageable initialize() {
public BasePageable initialize() {
this.page = DEFAULT_PAGE;
this.pageSize = UNPAGED_PAGE_SIZE;
this.offset = DEFAULT_OFFSET;
return this;
}

public Pageable initialize(long page, long pageSize, long firstRecordIndex) {
public BasePageable initialize(long page, long pageSize, long firstRecordIndex) {
this.page = Math.max(NumberUtils.toInt(page), DEFAULT_PAGE);
this.pageSize = Math.max(NumberUtils.toInt(pageSize), UNPAGED_PAGE_SIZE);
this.offset = Math.max(NumberUtils.toInt(firstRecordIndex), DEFAULT_OFFSET);
return this;
}

public static Pageable unpaged() {
public static BasePageable unpaged() {
return UNPAGED;
}

private static class UnpagedPageable extends Pageable {
private static class UnpagedPageable extends BasePageable {
}

public int getTotalPages() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,13 @@ public abstract class BaseRepository {
@Autowired
protected JPAQueryFactory queryFactory;

protected JPAQuery<?> pagingQuery(Pageable pageable) {
protected JPAQuery<?> pagingQuery(BasePageable pageable) {
return queryFactory.query()
.limit(pageable.getPageSize())
.offset(pageable.getOffset());
}

protected <T> JPAQuery<T> pagination(JPAQuery<T> query, Pageable pageable) {
protected <T> JPAQuery<T> pagination(JPAQuery<T> query, BasePageable pageable) {
return query
.limit(pageable.getPageSize())
.offset(pageable.getOffset());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,5 @@

public interface CreatePagination {

Pageable newPagination();
BasePageable newPagination();
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

@Getter
@Setter
public abstract class PaginatedContent<T> extends Pageable {
public abstract class PaginatedContent<T> extends BasePageable {

private static final long serialVersionUID = 4042588564593515879L;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import java.io.Serializable;
import java.util.HashSet;
import java.util.List;
import java.util.Optional;
import java.util.Set;
import java.util.function.Function;

Expand All @@ -13,7 +14,7 @@

@Slf4j
@Getter
public class UnionPageResizer extends Pageable {
public class UnionPageResizer extends BasePageable {

private static final long serialVersionUID = 7721966097602701397L;

Expand All @@ -30,15 +31,15 @@ private static class ResizedPage implements Serializable {

@EqualsAndHashCode.Include
private final Class<?> clazz;
private final Pageable pageable;
private final BasePageable pageable;
private final boolean merged;

private static ResizedPage unmerge(Pageable pageable) {
Pageable initialized = pageable.initialize();
private static ResizedPage unmerge(BasePageable pageable) {
BasePageable initialized = pageable.initialize();
return new ResizedPage(pageable.getClass(), initialized, false);
}

private static ResizedPage merge(Pageable pageable) {
private static ResizedPage merge(BasePageable pageable) {
return new ResizedPage(pageable.getClass(), pageable, true);
}

Expand All @@ -47,13 +48,13 @@ private long getTotalCount() {
}
}

public UnionPageResizer(Pageable unionPageable, List<CreatePagination> createPaginations) {
public UnionPageResizer(BasePageable unionPageable, List<CreatePagination> createPaginations) {
this.page = unionPageable.getPage();
this.pageSize = unionPageable.getPageSize();

long prevTotalCount = 0;
for (CreatePagination createPagination : createPaginations) {
Pageable pageable = createPagination.newPagination();
BasePageable pageable = createPagination.newPagination();
ResizedPage resizedPage = obtainResizedPage(pageable, prevTotalCount);
prevTotalCount += resizedPage.getTotalCount();
resizedPages.add(resizedPage);
Expand All @@ -62,19 +63,19 @@ public UnionPageResizer(Pageable unionPageable, List<CreatePagination> createPag
unionPageable.setTotalCount(getTotalCount());
}

public UnionPageResizer(int requestPage, int pageSize, List<Pageable> pageableList) {
public UnionPageResizer(int requestPage, int pageSize, List<BasePageable> pageableList) {
this.page = requestPage;
this.pageSize = pageSize;

long prevTotalCount = 0;
for (Pageable pageable : pageableList) {
for (BasePageable pageable : pageableList) {
ResizedPage resizedPage = obtainResizedPage(pageable, prevTotalCount);
prevTotalCount += resizedPage.getTotalCount();
resizedPages.add(resizedPage);
}
}

private ResizedPage obtainResizedPage(Pageable pageable, long prevTotalCount) {
private ResizedPage obtainResizedPage(BasePageable pageable, long prevTotalCount) {
final int dataPresent = 1;
final int resizingStartPage = getTotalPage(prevTotalCount + dataPresent, pageSize);
final int totalPageWithPrevPages = getTotalPageWithPrev(pageable, prevTotalCount);
Expand All @@ -87,11 +88,11 @@ private ResizedPage obtainResizedPage(Pageable pageable, long prevTotalCount) {
return ResizedPage.unmerge(pageable);
}

private int getTotalPageWithPrev(Pageable pageable, long prevTotalCount) {
private int getTotalPageWithPrev(BasePageable pageable, long prevTotalCount) {
return pageable.getTotalPage(pageable.getTotalCount() + prevTotalCount, pageSize);
}

private ResizedPage resizingPage(Pageable pageable, final long resizingStartPage, long prevTotalCount) {
private ResizedPage resizingPage(BasePageable pageable, final long resizingStartPage, long prevTotalCount) {
final long prevLastPageSize = getLastPageSize(prevTotalCount);

long zeroBasedPage = Math.max(page - resizingStartPage, 0);
Expand Down Expand Up @@ -129,7 +130,7 @@ private long getLastPageSize(long totalCount) {
return lastPageSize;
}

public boolean isMergedData(Pageable pageable) {
public boolean isMergedData(BasePageable pageable) {
return get(pageable.getClass())
.isMerged();
}
Expand All @@ -141,26 +142,26 @@ private ResizedPage get(Class<?> clazz) {
.orElseThrow(() -> new RuntimeException("not found page object."));
}

public <T extends Pageable> T getPagination(Class<T> clazz) {
Pageable pageable = get(clazz).getPageable();
public <T extends BasePageable> T getPagination(Class<T> clazz) {
BasePageable pageable = get(clazz).getPageable();
return clazz.cast(pageable);
}

public <DATA, T extends PaginatedContent<DATA>> T applyContent(Class<T> clazz, Function<T, DATA> contentProvider) {
public <DATA, T extends PaginatedContent<DATA>> Optional<DATA> applyContent(Class<T> clazz,
Function<T, DATA> contentProvider) {
ResizedPage resizedPage = get(clazz);
T paginatedContent = clazz.cast(resizedPage.getPageable());
if (resizedPage.isMerged()) {
DATA content = contentProvider.apply(paginatedContent);
paginatedContent.setContent(content);
T paginatedContent = clazz.cast(resizedPage.getPageable());
return Optional.of(contentProvider.apply(paginatedContent));
}

return paginatedContent;
return Optional.empty();
}

public long getTotalCount() {
return resizedPages.stream()
.map(ResizedPage::getPageable)
.mapToLong(Pageable::getTotalCount)
.mapToLong(BasePageable::getTotalCount)
.sum();
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,28 +11,28 @@
@RequiredArgsConstructor(access = AccessLevel.PRIVATE)
public class UnionPagination implements CreatePagination {

private static final BiFunction<Class<? extends Pageable>, Supplier<Long>, Pageable> PROVIDER;
private static final BiFunction<Class<? extends BasePageable>, Supplier<Long>, BasePageable> PROVIDER;

static {
PROVIDER = (clazz, executeCountQuery) -> {
Pageable paginatedContent = ReflectionUtils.newInstance(clazz);
BasePageable paginatedContent = ReflectionUtils.newInstance(clazz);
paginatedContent.setTotalCount(executeCountQuery.get());
return paginatedContent;
};
}

private final Class<? extends Pageable> pageableClass;
private final Class<? extends BasePageable> pageableClass;
private final Supplier<Long> executeCountQuery;

public static UnionPagination create(
Class<? extends Pageable> pageableClass,
Class<? extends BasePageable> pageableClass,
Supplier<Long> executeCountQuery
) {
return new UnionPagination(pageableClass, executeCountQuery);
}

@Override
public Pageable newPagination() {
public BasePageable newPagination() {
return PROVIDER.apply(pageableClass, executeCountQuery);
}
}
Original file line number Diff line number Diff line change
@@ -1,11 +1,16 @@
package com.gmoon.springjpapagination.users.user.api;

import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.web.PagedModel;
import org.springframework.http.HttpEntity;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import com.gmoon.springjpapagination.users.user.application.UserService;
import com.gmoon.springjpapagination.users.user.domain.User;
import com.gmoon.springjpapagination.users.user.dto.UserContentListVO;

import lombok.RequiredArgsConstructor;
Expand All @@ -19,8 +24,14 @@ public class UserRestController {

private final UserService userService;

@GetMapping
public ResponseEntity<UserContentListVO> findAll(UserContentListVO listVO) {
@GetMapping("/content")
public ResponseEntity<UserContentListVO> content(UserContentListVO listVO) {
return ResponseEntity.ok(userService.getUserContentListVO(listVO));
}

@GetMapping
public HttpEntity<PagedModel<User>> findAll(String groupId, String keyword, Pageable pageable) {
Page<User> content = userService.findAll(groupId, keyword, pageable);
return ResponseEntity.ok(new PagedModel<>(content));
}
}
Original file line number Diff line number Diff line change
@@ -1,16 +1,22 @@
package com.gmoon.springjpapagination.users.user.application;

import static com.gmoon.springjpapagination.users.user.domain.QUser.*;
import static java.util.Arrays.*;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.stream.Collectors;

import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.querydsl.core.types.Predicate;

import com.gmoon.springjpapagination.global.domain.UnionPageResizer;
import com.gmoon.springjpapagination.global.domain.UnionPagination;
import com.gmoon.springjpapagination.users.user.domain.User;
import com.gmoon.springjpapagination.users.user.domain.UserGroupRepository;
import com.gmoon.springjpapagination.users.user.domain.UserRepository;
import com.gmoon.springjpapagination.users.user.dto.UserContentListVO;
Expand Down Expand Up @@ -49,25 +55,35 @@ public UserContentListVO getUserContentListVO(UserContentListVO listVO) {
return listVO;
}

@Transactional(readOnly = true)
public Page<User> findAll(String groupId, String keyword, Pageable pageable) {
Predicate predicate = user.userGroup.id.eq(groupId)
.and(user.likeName(keyword));

return userRepository.findAll(predicate, pageable);
}

private void setContent(UserContentListVO listVO, UnionPageResizer resizer) {
UserContentListVO.Search search = listVO.getSearch();

List<UserContentVO> groups = resizer.applyContent(
UserGroupListVO.class,
pageable ->
userGroupRepository.findAll(search.getGroupId(), search.getKeyword(), pageable)
).getContent()
)
.stream()
.flatMap(Collection::stream)
.map(UserContentVO::new)
.collect(Collectors.toList());
.toList();

List<UserContentVO> users = resizer.applyContent(
UserListVO.class,
pageable -> userRepository.findAll(search.getGroupId(), search.getKeyword(), pageable)
).getContent()
)
.stream()
.flatMap(Collection::stream)
.map(UserContentVO::new)
.collect(Collectors.toList());
.toList();

List<UserContentVO> content = new ArrayList<>(listVO.getPageSize());
content.addAll(groups);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,11 @@

import java.util.List;

import com.gmoon.springjpapagination.global.domain.Pageable;
import com.gmoon.springjpapagination.global.domain.BasePageable;

public interface UserGroupRepository {

List<UserGroup> findAll(String groupId, String keyword, Pageable pageable);
List<UserGroup> findAll(String groupId, String keyword, BasePageable pageable);

long countBy(String groupId, String keyword);
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,18 @@

import java.util.List;

import com.gmoon.springjpapagination.global.domain.Pageable;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;

import com.querydsl.core.types.Predicate;

import com.gmoon.springjpapagination.global.domain.BasePageable;

public interface UserRepository {

List<User> findAll(String groupId, String keyword, Pageable pageable);
List<User> findAll(String groupId, String keyword, BasePageable pageable);

Page<User> findAll(Predicate predicate, Pageable pageable);

long countBy(String groupId, String keyword);
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.gmoon.springjpapagination.users.user.dto;

import java.io.Serial;
import java.io.Serializable;
import java.util.List;

Expand All @@ -15,6 +16,7 @@
@ToString
public class UserContentListVO extends PaginatedContent<List<UserContentVO>> {

@Serial
private static final long serialVersionUID = -6252002883733589738L;

private static final int DEFAULT_PAGE_SIZE = 10;
Expand Down
Loading

0 comments on commit 62c3027

Please sign in to comment.