Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

QueryDSL 래핑 클래스 추가 #240

Merged
merged 1 commit into from
Feb 21, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,57 +1,45 @@
package org.hyunggi.mygardenbe.boards.learn.repository;

import com.querydsl.core.types.Order;
import com.querydsl.core.types.OrderSpecifier;
import com.querydsl.core.types.dsl.BooleanExpression;
import com.querydsl.core.types.dsl.PathBuilder;
import com.querydsl.jpa.impl.JPAQuery;
import com.querydsl.jpa.impl.JPAQueryFactory;
import jakarta.persistence.EntityManager;
import org.hyunggi.mygardenbe.boards.learn.entity.LearnBoardEntity;
import org.hyunggi.mygardenbe.common.querydsl.support.Querydsl4RepositorySupport;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.support.PageableExecutionUtils;
import org.springframework.util.StringUtils;

import java.time.LocalDateTime;
import java.util.List;
import java.util.function.Function;

import static org.hyunggi.mygardenbe.boards.learn.entity.QLearnBoardEntity.learnBoardEntity;

public class LearnBoardRepositoryCustomImpl implements LearnBoardRepositoryCustom {
private final JPAQueryFactory queryFactory;

public LearnBoardRepositoryCustomImpl(EntityManager em) {
this.queryFactory = new JPAQueryFactory(em);
public class LearnBoardRepositoryCustomImpl extends Querydsl4RepositorySupport implements LearnBoardRepositoryCustom {
public LearnBoardRepositoryCustomImpl() {
super(LearnBoardEntity.class);
}

@Override
public Page<LearnBoardEntity> searchLearnBoards(final LocalDateTime startDateTime, final LocalDateTime endDateTime, final String category, final String searchText, final Pageable pageable) {
final List<LearnBoardEntity> content = getContent(startDateTime, endDateTime, category, searchText, pageable);
final JPAQuery<Long> countQuery = getJpaQuery(startDateTime, endDateTime, category, searchText);

return PageableExecutionUtils.getPage(content, pageable, countQuery::fetchOne);
return applyPagination(
pageable,
getContentQuery(startDateTime, endDateTime, category, searchText),
getCountQuery(startDateTime, endDateTime, category, searchText)
);
}

private List<LearnBoardEntity> getContent(final LocalDateTime startDateTime, final LocalDateTime endDateTime, final String category, final String searchText, final Pageable pageable) {
final var query = queryFactory
private Function<JPAQueryFactory, JPAQuery> getContentQuery(final LocalDateTime startDateTime, final LocalDateTime endDateTime, final String category, final String searchText) {
return queryFactory -> queryFactory
.selectFrom(learnBoardEntity)
.where(
writtenAtBetween(startDateTime, endDateTime),
categoryEquals(category),
searchTextContains(searchText)
)
.offset(pageable.getOffset())
.limit(pageable.getPageSize());

addOrderBy(query, pageable);

return query.fetch();
);
}

private JPAQuery<Long> getJpaQuery(final LocalDateTime startDateTime, final LocalDateTime endDateTime, final String category, final String searchText) {
return queryFactory
private Function<JPAQueryFactory, JPAQuery<Long>> getCountQuery(final LocalDateTime startDateTime, final LocalDateTime endDateTime, final String category, final String searchText) {
return queryFactory -> queryFactory
.select(learnBoardEntity.count())
.from(learnBoardEntity)
.where(
Expand Down Expand Up @@ -80,12 +68,4 @@ private BooleanExpression searchTextContains(final String searchText) {

return learnBoardEntity.title.contains(searchText).or(learnBoardEntity.content.contains(searchText));
}

private void addOrderBy(final JPAQuery<LearnBoardEntity> query, final Pageable pageable) {
for (Sort.Order order : pageable.getSort()) {
PathBuilder pathBuilder = new PathBuilder(learnBoardEntity.getType(), learnBoardEntity.getMetadata());

query.orderBy(new OrderSpecifier<>(order.isAscending() ? Order.ASC : Order.DESC, pathBuilder.get(order.getProperty())));
}
}
}
Original file line number Diff line number Diff line change
@@ -1,58 +1,45 @@
package org.hyunggi.mygardenbe.boards.notice.repository;

import com.querydsl.core.types.Order;
import com.querydsl.core.types.OrderSpecifier;
import com.querydsl.core.types.dsl.BooleanExpression;
import com.querydsl.core.types.dsl.PathBuilder;
import com.querydsl.jpa.impl.JPAQuery;
import com.querydsl.jpa.impl.JPAQueryFactory;
import jakarta.persistence.EntityManager;
import org.hyunggi.mygardenbe.boards.notice.entity.NoticeBoardEntity;
import org.hyunggi.mygardenbe.common.querydsl.support.Querydsl4RepositorySupport;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.support.PageableExecutionUtils;
import org.springframework.util.StringUtils;

import java.time.LocalDateTime;
import java.util.List;
import java.util.function.Function;

import static org.hyunggi.mygardenbe.boards.notice.entity.QNoticeBoardEntity.noticeBoardEntity;


public class NoticeBoardRepositoryCustomImpl implements NoticeBoardRepositoryCustom {
private final JPAQueryFactory queryFactory;

public NoticeBoardRepositoryCustomImpl(EntityManager em) {
this.queryFactory = new JPAQueryFactory(em);
public class NoticeBoardRepositoryCustomImpl extends Querydsl4RepositorySupport implements NoticeBoardRepositoryCustom {
public NoticeBoardRepositoryCustomImpl() {
super(NoticeBoardEntity.class);
}

@Override
public Page<NoticeBoardEntity> searchNoticeBoards(final LocalDateTime startDateTime, final LocalDateTime endDateTime, final String category, final String searchText, final Pageable pageable) {
final List<NoticeBoardEntity> content = getContent(startDateTime, endDateTime, category, searchText, pageable);
final JPAQuery<Long> countQuery = getJpaQuery(startDateTime, endDateTime, category, searchText);

return PageableExecutionUtils.getPage(content, pageable, countQuery::fetchOne);
return applyPagination(
pageable,
getContentQuery(startDateTime, endDateTime, category, searchText),
getCountQuery(startDateTime, endDateTime, category, searchText)
);
}

private List<NoticeBoardEntity> getContent(final LocalDateTime startDateTime, final LocalDateTime endDateTime, final String category, final String searchText, final Pageable pageable) {
final var query = queryFactory
private Function<JPAQueryFactory, JPAQuery> getContentQuery(final LocalDateTime startDateTime, final LocalDateTime endDateTime, final String category, final String searchText) {
return queryFactory -> queryFactory
.selectFrom(noticeBoardEntity)
.where(
writtenAtBetween(startDateTime, endDateTime),
categoryEquals(category),
searchTextContains(searchText)
)
.offset(pageable.getOffset())
.limit(pageable.getPageSize());

addOrderBy(query, pageable);

return query.fetch();
);
}

private JPAQuery<Long> getJpaQuery(final LocalDateTime startDateTime, final LocalDateTime endDateTime, final String category, final String searchText) {
return queryFactory
private Function<JPAQueryFactory, JPAQuery<Long>> getCountQuery(final LocalDateTime startDateTime, final LocalDateTime endDateTime, final String category, final String searchText) {
return queryFactory -> queryFactory
.select(noticeBoardEntity.count())
.from(noticeBoardEntity)
.where(
Expand Down Expand Up @@ -81,12 +68,4 @@ private BooleanExpression searchTextContains(final String searchText) {

return noticeBoardEntity.title.contains(searchText).or(noticeBoardEntity.content.contains(searchText));
}

private void addOrderBy(final JPAQuery<NoticeBoardEntity> query, final Pageable pageable) {
for (Sort.Order order : pageable.getSort()) {
PathBuilder pathBuilder = new PathBuilder(noticeBoardEntity.getType(), noticeBoardEntity.getMetadata());

query.orderBy(new OrderSpecifier<>(order.isAscending() ? Order.ASC : Order.DESC, pathBuilder.get(order.getProperty())));
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
package org.hyunggi.mygardenbe.common.querydsl.support;

import com.querydsl.core.types.EntityPath;
import com.querydsl.core.types.Expression;
import com.querydsl.core.types.dsl.PathBuilder;
import com.querydsl.jpa.impl.JPAQuery;
import com.querydsl.jpa.impl.JPAQueryFactory;
import jakarta.annotation.PostConstruct;
import jakarta.persistence.EntityManager;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.repository.support.JpaEntityInformation;
import org.springframework.data.jpa.repository.support.JpaEntityInformationSupport;
import org.springframework.data.jpa.repository.support.Querydsl;
import org.springframework.data.querydsl.SimpleEntityPathResolver;
import org.springframework.data.support.PageableExecutionUtils;
import org.springframework.stereotype.Repository;
import org.springframework.util.Assert;

import java.util.List;
import java.util.function.Function;

/**
* Querydsl 4.x 버전에 맞춘 Querydsl 지원 라이브러리
*
* @author Younghan Kim
* @see org.springframework.data.jpa.repository.support.QuerydslRepositorySupport
*/
@Repository
public abstract class Querydsl4RepositorySupport {
private final Class domainClass;
private Querydsl querydsl;
private EntityManager entityManager;
private JPAQueryFactory queryFactory;

protected Querydsl4RepositorySupport(Class<?> domainClass) {
Assert.notNull(domainClass, "Domain class must not be null!");
this.domainClass = domainClass;
}

@PostConstruct
public void validate() {
Assert.notNull(entityManager, "EntityManager must not be null!");
Assert.notNull(querydsl, "Querydsl must not be null!");
Assert.notNull(queryFactory, "QueryFactory must not be null!");
}

protected JPAQueryFactory getQueryFactory() {
return queryFactory;
}

protected Querydsl getQuerydsl() {
return querydsl;
}

protected EntityManager getEntityManager() {
return entityManager;
}

@Autowired
public void setEntityManager(EntityManager entityManager) {
Assert.notNull(entityManager, "EntityManager must not be null!");

JpaEntityInformation entityInformation = JpaEntityInformationSupport.getEntityInformation(domainClass, entityManager);
SimpleEntityPathResolver resolver = SimpleEntityPathResolver.INSTANCE;
EntityPath path = resolver.createPath(entityInformation.getJavaType());

this.entityManager = entityManager;
this.querydsl = new Querydsl(entityManager, new PathBuilder<>(path.getType(), path.getMetadata()));
this.queryFactory = new JPAQueryFactory(entityManager);
}

protected <T> JPAQuery<T> select(Expression<T> expr) {
return getQueryFactory().select(expr);
}

protected <T> JPAQuery<T> selectFrom(EntityPath<T> from) {
return getQueryFactory().selectFrom(from);
}

protected <T> Page<T> applyPagination(Pageable pageable,
Function<JPAQueryFactory, JPAQuery> contentQuery,
Function<JPAQueryFactory, JPAQuery<Long>> countQuery) {
JPAQuery jpaContentQuery = contentQuery.apply(getQueryFactory());
List<T> content = getQuerydsl().applyPagination(pageable, jpaContentQuery).fetch();
JPAQuery<Long> countResult = countQuery.apply(getQueryFactory());

return PageableExecutionUtils.getPage(content, pageable, countResult::fetchOne);
}
}
Loading