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

Refactoring -dsl 쿼리 개선 및 리팩토링 이슈해결 #81

Merged
merged 8 commits into from
Jun 19, 2023
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
Expand Up @@ -35,7 +35,6 @@ public class MyInfoDto {
private Integer minAge;
private Integer maxAge;

private String preferredAge;
private Integer myAge;
private String detail;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,18 +12,24 @@
import com.fab.banggabgo.type.Gender;
import com.fab.banggabgo.type.Period;
import com.fab.banggabgo.type.Seoul;
import com.querydsl.core.types.dsl.BooleanExpression;
import com.querydsl.jpa.impl.JPAQueryFactory;
import java.util.List;
import java.util.stream.Collectors;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.Pageable;
import org.springframework.util.StringUtils;

@RequiredArgsConstructor
public class ArticleRepositoryImpl implements ArticleRepositoryCustom {

private final JPAQueryFactory queryFactory;

@Value("${query.default.static}")
private String default_option;
QArticle qArticle = QArticle.article;
QUser qUser = QUser.user;
QLikeArticle qLikeArticle= QLikeArticle.likeArticle;
Expand All @@ -34,7 +40,7 @@ public Page<Article> getArticle(Pageable pageable, boolean isRecruiting) {
.join(qArticle.user, qUser)
.fetchJoin()
.orderBy(qArticle.createDate.desc())
.where(qArticle.isDeleted.eq(false))
.where(eqDelete(false),eqRecruiting(true))
.offset(pageable.getOffset())
.limit(pageable.getPageSize())
.distinct();
Expand Down Expand Up @@ -64,42 +70,23 @@ public Page<Article> getArticleByFilter(Pageable pageable, boolean isRecruiting,
.join(qArticle.user, qUser)
.fetchJoin()
.orderBy(qArticle.createDate.desc())
.where(qArticle.isDeleted.eq(false))
.where(eqDelete(false)
,eqRecruiting(true)
,eqGender(gender)
,eqPeriod(period)
,eqRegion(region)
,loePrice(price))
.offset(pageable.getOffset())
.limit(pageable.getPageSize())
.distinct();


var articleCountQuery = queryFactory.select(qArticle.count())
.from(qArticle)
.join(qArticle.user, qUser)
.where(qArticle.isDeleted.eq(false))
.distinct();

if (isRecruiting) {
articleQuery = articleQuery.where(qArticle.isRecruiting.eq(true));
articleCountQuery = articleCountQuery.where(qArticle.isRecruiting.eq(true));
}

if (!"상관 없음".equals(region)) {
articleQuery = articleQuery.where(qArticle.region.eq(Seoul.fromValue(region)));
articleCountQuery = articleCountQuery.where(qArticle.region.eq(Seoul.fromValue(region)));
}

if (!"상관 없음".equals(period)) {
articleQuery = articleQuery.where(qArticle.period.eq(Period.fromValue(period)));
articleCountQuery = articleCountQuery.where(qArticle.period.eq(Period.fromValue(period)));
}

if (!"상관 없음".equals(price)) {
articleQuery = articleQuery.where(qArticle.price.loe(Integer.parseInt(price)));
articleCountQuery = articleCountQuery.where(qArticle.price.loe(Integer.parseInt(price)));
}

if (!"상관 없음".equals(gender)) {
articleQuery = articleQuery.where(qArticle.gender.eq(Gender.fromValue(gender)));
articleCountQuery = articleCountQuery.where(qArticle.gender.eq(Gender.fromValue(gender)));
}

List<Article> articleList = articleQuery.fetch();

return new PageImpl<>(articleList, pageable, articleCountQuery.fetchOne());
Expand All @@ -109,7 +96,7 @@ public Page<Article> getArticleByFilter(Pageable pageable, boolean isRecruiting,
public Integer getArticleTotalCnt() {
return Math.toIntExact(queryFactory.select(qArticle.count())
.from(qArticle)
.where(qArticle.isDeleted.eq(false))
.where(eqDelete(false))
.fetchFirst());
}

Expand All @@ -118,7 +105,7 @@ public List<MyArticleDto> getMyArticle(User user) {
var getMyArticleQuery=queryFactory.selectFrom(qArticle)
.join(qArticle.user ,qUser)
.fetchJoin()
.where(qUser.eq(user).and(qArticle.isDeleted.eq(false)))
.where(qUser.eq(user),eqDelete(false))
.orderBy(qArticle.isRecruiting.desc() ,qArticle.createDate.desc());
return getMyArticleQuery.fetch()
.stream().map(MyArticleDto::toDto)
Expand All @@ -132,7 +119,8 @@ public List<FavoriteArticleDto> getFavoriteArticle(User user){
.from(qLikeArticle)
.join(qLikeArticle.article,qArticle)
.join(qLikeArticle.user,qUser)
.where(qUser.eq(user).and(qArticle.isDeleted.eq(false)));
.where(qUser.eq(user),
eqDelete(false));

return getMyFavoriteArticleQuery.fetch()
.stream().map(FavoriteArticleDto::toDto)
Expand All @@ -144,13 +132,32 @@ public List<ArticleInfoDto> getUserArticle(User user) {
var getUserArticleQuery = queryFactory.selectFrom(qArticle)
.join(qArticle.user, qUser)
.fetchJoin()
.where(qUser.eq(user)
.and(qArticle.isDeleted.eq(false))
.and(qArticle.isRecruiting.eq(true)))
.where(qUser.eq(user),
eqDelete(false),
eqRecruiting(true))
.orderBy(qArticle.createDate.desc());

return getUserArticleQuery.fetch()
.stream().map(ArticleInfoDto::toDto)
.collect(Collectors.toList());
}

private BooleanExpression eqDelete(boolean deleted){
return qArticle.isDeleted.eq(deleted);
}
private BooleanExpression eqRecruiting(boolean isRecruiting){
return qArticle.isRecruiting.eq(isRecruiting);
}
private BooleanExpression eqPeriod(String period){
return StringUtils.hasText(period)&&!period.equals(default_option)? qArticle.period.eq(Period.fromValue(period)):null;
}
private BooleanExpression eqGender(String gender){
return StringUtils.hasText(gender)&&!gender.equals(default_option)? qArticle.gender.eq(Gender.fromValue(gender)):null;
}
private BooleanExpression eqRegion(String region){
return StringUtils.hasText(region)&&!region.equals(default_option)? qArticle.region.eq(Seoul.fromValue(region)):null;
}
private BooleanExpression loePrice(String price){
return StringUtils.hasText(price)&&!price.equals(default_option)? qArticle.price.loe(Integer.parseInt(price)):null;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,10 @@
import com.fab.banggabgo.entity.QUser;
import com.fab.banggabgo.entity.User;
import com.fab.banggabgo.repository.UserRepositoryCustom;
import com.querydsl.core.types.dsl.BooleanExpression;
import com.querydsl.core.types.dsl.Expressions;
import com.querydsl.jpa.JPAExpressions;
import com.querydsl.jpa.JPQLQuery;
import com.querydsl.jpa.impl.JPAQueryFactory;
import java.util.List;
import java.util.Optional;
Expand All @@ -18,12 +20,12 @@ public class UserRepositoryImpl implements UserRepositoryCustom {
QUser qUser = QUser.user;
QArticle qArticle = QArticle.article;

@Override
public Optional<User> findByEmail(String email) {
var query = queryFactory.selectFrom(qUser)
.leftJoin(qUser.roles).fetchJoin()
.leftJoin(qUser.tag).fetchJoin()
.leftJoin(qUser.tag).fetchJoin()
.where(qUser.email.eq(email));
.where(eqEmail(email));
return Optional.ofNullable(query.fetchOne());
}

Expand All @@ -36,18 +38,49 @@ public List<User> getRecommend(User user, Integer size) {
.and(qArticle.isRecruiting.eq(true)));

var userQuery = queryFactory.selectFrom(qUser)
.where(qUser.gender.eq(user.getGender())
.and(qUser.isSmoker.eq(user.getIsSmoker()))
.and(qUser.region.eq(user.getRegion()))
.and(qUser.activityTime.eq(user.getActivityTime()))
.and(qUser.minAge.eq(user.getMinAge()))
.and(qUser.maxAge.eq(user.getMaxAge()))
.and(qUser.id.ne(user.getId()))
.and(qUser.in(subQuery)))
.where(eqGender(user),
eqSmoker(user),
preferAge(user),
eqRegion(user),
neSelf(user),
eqActivityTime(user),
userInSubQuery(subQuery)
)
.orderBy(Expressions.numberTemplate(Double.class, "function('rand')").asc())
.limit(size);

return userQuery.fetch();
}

BooleanExpression eqEmail(String email){
return qUser.email.eq(email);
}

BooleanExpression eqGender(User user) {
return qUser.gender.eq(user.getGender());
}

BooleanExpression eqSmoker(User user) {
return qUser.isSmoker.eq(user.getIsSmoker());
}

BooleanExpression preferAge(User user) {
return qUser.myAge.between(user.getMinAge(), user.getMaxAge());
}

BooleanExpression eqRegion(User user) {
return qUser.region.eq(user.getRegion());
}

BooleanExpression userInSubQuery(JPQLQuery<User> sub_query) {
return qUser.in(sub_query);
}

BooleanExpression neSelf(User user) {
return qUser.id.ne(user.getId());
}

BooleanExpression eqActivityTime(User user) {
return qUser.activityTime.eq(user.getActivityTime());
}
}
12 changes: 0 additions & 12 deletions src/main/java/com/fab/banggabgo/type/PreferredAge.java

This file was deleted.

5 changes: 4 additions & 1 deletion src/main/resources/application.yml
Original file line number Diff line number Diff line change
Expand Up @@ -27,4 +27,7 @@ spring:
enabled: true

server:
port: 8080
port: 8080
query:
default:
static: "상관 없음"
2 changes: 1 addition & 1 deletion src/main/resources/aws-example.yml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
cloud:
sws:
aws:
s3:
bucket: your-bucket!
credentials:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -215,19 +215,20 @@ void FailNonAuthGetApplicantList() throws Exception {
.with(SecurityMockMvcRequestPostProcessors.csrf()))
.andExpect(status().isUnauthorized());
}
}

@Test
@DisplayName("이미지 변경 테스트")
@WithMockUser
void postMyImg() throws Exception {
Path imagePath = Paths.get("src/test/resources/wierd.png");
byte[] imageBytes = Files.readAllBytes(imagePath);
var image = new MockMultipartFile("image", "wierd.png", MediaType.IMAGE_PNG_VALUE, imageBytes);
mockMvc.perform(MockMvcRequestBuilders.multipart("/api/my/image")
.file(image)
.with(SecurityMockMvcRequestPostProcessors.csrf())
)
.andExpect(status().isOk());

@Test
@DisplayName("이미지 변경 테스트")
@WithMockUser
void postMyImg() throws Exception {
Path imagePath = Paths.get("src/test/resources/wierd.png");
byte[] imageBytes = Files.readAllBytes(imagePath);
var image = new MockMultipartFile("image", "wierd.png", MediaType.IMAGE_PNG_VALUE,
imageBytes);
mockMvc.perform(MockMvcRequestBuilders.multipart("/api/my/image")
.file(image)
.with(SecurityMockMvcRequestPostProcessors.csrf())
)
.andExpect(status().isOk());
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -278,11 +278,11 @@ class fromApplicant {
void getApplicantsSuccess() {

when(applyRepository.getMyApplicant(any(), anyInt())).thenReturn(List.of(Apply.builder()
.approveStatus(ApproveStatus.WAIT)
.article(article)
.applicantUser(appliedUser)
.approveStatus(ApproveStatus.WAIT)
.build()));
.approveStatus(ApproveStatus.WAIT)
.article(article)
.applicantUser(appliedUser)
.approveStatus(ApproveStatus.WAIT)
.build()));

var result = myContentService.getMyFromApplicantList(loginUser, 4, 1);

Expand All @@ -292,7 +292,8 @@ void getApplicantsSuccess() {
assertEquals(result.get(0).getArticleId(), article.getId());
assertEquals(result.get(0).getOtherUserName(), appliedUser.getNickname());
assertEquals(result.get(0).getOtherUserId(), appliedUser.getId());

}

@Test
@DisplayName("이미지 업로드하기")
void postImage() throws IOException {
Expand Down