Skip to content

Commit

Permalink
Feat :. 무한스크롤 방식 필터 조회 쿼리 구현 및 조건 쿼리 메서드 분리 리팩토링
Browse files Browse the repository at this point in the history
  • Loading branch information
byeolhaha committed Dec 2, 2023
1 parent 364c1f7 commit cfa1f87
Show file tree
Hide file tree
Showing 6 changed files with 232 additions and 67 deletions.
Original file line number Diff line number Diff line change
@@ -1,10 +1,8 @@
package org.guzzing.studayserver.domain.academy.repository.academy;

import java.util.List;
import org.guzzing.studayserver.domain.academy.repository.dto.AcademiesByLocation;
import org.guzzing.studayserver.domain.academy.repository.dto.AcademiesByLocationWithScroll;
import org.guzzing.studayserver.domain.academy.repository.dto.AcademyByFiltering;
import org.guzzing.studayserver.domain.academy.repository.dto.AcademyFilterCondition;

import org.guzzing.studayserver.domain.academy.repository.dto.*;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Slice;

Expand All @@ -19,4 +17,10 @@ AcademiesByLocationWithScroll findAcademiesByLocation(
Long memberId,
int pageNumber,
int pageSize);

AcademiesByFilterWithScroll filterAcademies(
AcademyFilterCondition academyFilterCondition,
Long memberId,
int pageNumber,
int pageSize);
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,11 @@

import jakarta.persistence.EntityManager;
import jakarta.persistence.Query;

import java.util.List;

import org.guzzing.studayserver.domain.academy.repository.dto.*;
import org.hibernate.query.NativeQuery;
import org.hibernate.transform.ResultTransformer;
import org.hibernate.type.StandardBasicTypes;

Expand All @@ -18,16 +21,24 @@ public AcademyQueryRepositoryImpl(EntityManager em) {
public List<AcademiesByLocation> findAcademiesByLocation(String pointFormat, Long memberId) {

String nativeQuery = """
SELECT a.id AS academyId, a.academy_name AS academyName, a.phone_number AS phoneNumber, a.full_address AS fullAddress,
a.latitude AS latitude , a.longitude AS longitude, a.shuttle AS shuttleAvailable,
(CASE WHEN l.academy_id IS NOT NULL THEN true ELSE false END) AS isLiked,
ac.category_id as categoryId
FROM academies AS a
LEFT JOIN academy_categories as ac
ON a.id = ac.academy_id
LEFT JOIN likes AS l
ON a.id = l.academy_id AND l.member_id = %s
WHERE MBRContains(ST_LINESTRINGFROMTEXT(%s), a.point)=1""";
SELECT
a.id AS academyId,
a.academy_name AS academyName,
a.phone_number AS phoneNumber,
a.full_address AS fullAddress,
a.latitude AS latitude ,
a.longitude AS longitude,
a.shuttle AS shuttleAvailable,
(CASE WHEN l.academy_id IS NOT NULL THEN true ELSE false END) AS isLiked,
ac.category_id as categoryId
FROM
academies AS a
LEFT JOIN
academy_categories as ac ON a.id = ac.academy_id
LEFT JOIN
likes AS l ON a.id = l.academy_id AND l.member_id = %s
WHERE
MBRContains(ST_LINESTRINGFROMTEXT(%s), a.point)=1""";

String formattedQuery = String.format(nativeQuery, memberId, pointFormat);

Expand Down Expand Up @@ -74,25 +85,27 @@ public List transformList(List collection) {

public List<AcademyByFiltering> filterAcademies(AcademyFilterCondition academyFilterCondition, Long memberId) {
String nativeQuery = """
SELECT a.id AS academyId, a.academy_name AS academyName, a.full_address AS fullAddress,
a.phone_number AS phoneNumber, a.latitude, a.longitude, a.shuttle AS shuttleAvailable,
ac.category_id as categoryId,
(CASE WHEN l.academy_id IS NOT NULL THEN true ELSE false END) AS isLiked
FROM academy_categories as ac
LEFT JOIN academies AS a ON ac.academy_id = a.id
LEFT JOIN likes AS l ON a.id = l.academy_id AND l.member_id = %s
WHERE MBRContains(ST_LINESTRINGFROMTEXT(%s), a.point)=1""";
SELECT
a.id AS academyId,
a.academy_name AS academyName,
a.full_address AS fullAddress,
a.phone_number AS phoneNumber,
a.latitude,
a.longitude,
a.shuttle AS shuttleAvailable,
ac.category_id as categoryId,
(CASE WHEN l.academy_id IS NOT NULL THEN true ELSE false END) AS isLiked
FROM
academy_categories as ac
LEFT JOIN
academies AS a ON ac.academy_id = a.id
LEFT JOIN
likes AS l ON a.id = l.academy_id AND l.member_id = %s
WHERE
MBRContains(ST_LINESTRINGFROMTEXT(%s), a.point)=1""";

String formattedQuery = String.format(nativeQuery, memberId, academyFilterCondition.pointFormat());

if (academyFilterCondition.categories() != null && !academyFilterCondition.categories().isEmpty()) {
formattedQuery += " AND ac.category_id IN " + academyFilterCondition.categories();
}

if (academyFilterCondition.desiredMinAmount() != null && academyFilterCondition.desiredMaxAmount() != null) {
formattedQuery += " AND max_education_fee BETWEEN " + academyFilterCondition.desiredMinAmount() + " AND "
+ academyFilterCondition.desiredMaxAmount();
}
formattedQuery = addWhereConditionsWithFilter(formattedQuery, academyFilterCondition);

Query query = em.createNativeQuery(formattedQuery);

Expand Down Expand Up @@ -139,33 +152,91 @@ public AcademiesByLocationWithScroll findAcademiesByLocation(
int pageSize) {

String nativeQuery = """
SELECT
a.id AS academyId,
a.academy_name AS academyName,
a.phone_number AS phoneNumber,
a.full_address AS fullAddress,
a.latitude AS latitude,
a.longitude AS longitude,
a.shuttle AS shuttleAvailable,
(CASE WHEN l.academy_id IS NOT NULL THEN true ELSE false END) AS isLiked
FROM
academies AS a
LEFT JOIN
likes AS l ON a.id = l.academy_id AND l.member_id = %s
WHERE
MBRContains(ST_LINESTRINGFROMTEXT(%s), a.point) = 1
ORDER BY a.academy_name
LIMIT %s OFFSET %s""";

int offset = pageNumber * pageSize;
SELECT
a.id AS academyId,
a.academy_name AS academyName,
a.phone_number AS phoneNumber,
a.full_address AS fullAddress,
a.latitude AS latitude,
a.longitude AS longitude,
a.shuttle AS shuttleAvailable,
(CASE WHEN l.academy_id IS NOT NULL THEN true ELSE false END) AS isLiked
FROM
academies AS a
LEFT JOIN
likes AS l ON a.id = l.academy_id AND l.member_id = %s
WHERE
MBRContains(ST_LINESTRINGFROMTEXT(%s), a.point) = 1
ORDER BY a.academy_name""";

String formattedQuery = String.format(nativeQuery, memberId, pointFormat, pageSize, offset);
String formattedQuery = String.format(nativeQuery, memberId, pointFormat);
formattedQuery = makeScroll(pageNumber, pageSize, formattedQuery);

Query emNativeQuery = em.createNativeQuery(
formattedQuery);

List<AcademyByLocationWithScroll> academiesByLocation =
emNativeQuery.unwrap(org.hibernate.query.NativeQuery.class)
.addScalar("academyId", StandardBasicTypes.LONG)
.addScalar("academyName", StandardBasicTypes.STRING)
.addScalar("fullAddress", StandardBasicTypes.STRING)
.addScalar("phoneNumber", StandardBasicTypes.STRING)
.addScalar("latitude", StandardBasicTypes.DOUBLE)
.addScalar("longitude", StandardBasicTypes.DOUBLE)
.addScalar("shuttleAvailable", StandardBasicTypes.STRING)
.addScalar("isLiked", StandardBasicTypes.BOOLEAN)
.setResultTransformer((tuple, aliases) -> new AcademyByLocationWithScroll(
(Long) tuple[0],
(String) tuple[1],
(String) tuple[2],
(String) tuple[3],
(Double) tuple[4],
(Double) tuple[5],
(String) tuple[6],
(boolean) tuple[7]
))
.getResultList();

return AcademiesByLocationWithScroll.of(
academiesByLocation,
isHasNest(academiesByLocation.size(), pageSize)
);
}

public AcademiesByFilterWithScroll filterAcademies(
AcademyFilterCondition academyFilterCondition,
Long memberId,
int pageNumber,
int pageSize) {
String nativeQuery = """
SELECT
a.id AS academyId,
a.academy_name AS academyName,
a.full_address AS fullAddress,
a.phone_number AS phoneNumber,
a.latitude, a.longitude,
a.shuttle AS shuttleAvailable,
(CASE WHEN l.academy_id IS NOT NULL THEN true ELSE false END) AS isLiked
FROM
academy_categories as ac
LEFT JOIN
academies AS a ON ac.academy_id = a.id
LEFT JOIN
likes AS l ON a.id = l.academy_id AND l.member_id = %s
WHERE
MBRContains(ST_LINESTRINGFROMTEXT(%s), a.point)=1""";


String formattedQuery = String.format(
nativeQuery,
memberId,
academyFilterCondition.pointFormat());
formattedQuery = addWhereConditionsWithFilter(formattedQuery, academyFilterCondition);
formattedQuery = makeScroll(pageNumber, pageSize, formattedQuery);

Query query = em.createNativeQuery(formattedQuery);

List<AcademyByFilterWithScroll> academyByFilter = query.unwrap(NativeQuery.class)
.addScalar("academyId", StandardBasicTypes.LONG)
.addScalar("academyName", StandardBasicTypes.STRING)
.addScalar("fullAddress", StandardBasicTypes.STRING)
Expand All @@ -174,26 +245,65 @@ public AcademiesByLocationWithScroll findAcademiesByLocation(
.addScalar("longitude", StandardBasicTypes.DOUBLE)
.addScalar("shuttleAvailable", StandardBasicTypes.STRING)
.addScalar("isLiked", StandardBasicTypes.BOOLEAN)
.setResultTransformer((tuple, aliases) -> new AcademyByLocationWithScroll(
(Long) tuple[0],
(String) tuple[1],
(String) tuple[2],
(String) tuple[3],
(Double) tuple[4],
(Double) tuple[5],
(String) tuple[6],
(boolean) tuple[7]
))
.setResultTransformer(
new ResultTransformer() {
@Override
public Object transformTuple(Object[] tuple, String[] aliases) {
return new AcademyByFilterWithScroll(
(Long) tuple[0],
(String) tuple[1],
(String) tuple[2],
(String) tuple[3],
(Double) tuple[4],
(Double) tuple[5],
(String) tuple[6],
(boolean) tuple[7]
);
}

@Override
public List transformList(List collection) {
return collection;
}
}
)
.getResultList();

return AcademiesByLocationWithScroll.of(
academiesByLocation,
isHasNest(academiesByLocation,pageSize)
return AcademiesByFilterWithScroll.of(
academyByFilter,
isHasNest(academyByFilter.size(), pageSize)
);
}

private boolean isHasNest(List<AcademyByLocationWithScroll> academiesByLocation, int pageSize) {
return academiesByLocation.size() == pageSize;
private boolean isHasNest(int resultSize, int pageSize) {
return resultSize == pageSize;
}

private String addWhereConditionsWithFilter(String formattedQuery, AcademyFilterCondition academyFilterCondition) {
formattedQuery += whereInCategories(academyFilterCondition);
formattedQuery += whereBetweenEducationFee(academyFilterCondition);
return formattedQuery;
}

private String whereInCategories(AcademyFilterCondition academyFilterCondition) {
if (academyFilterCondition.categories() != null && !academyFilterCondition.categories().isEmpty()) {
return " AND ac.category_id IN " + academyFilterCondition.categories();
}
return "";
}

private String whereBetweenEducationFee(AcademyFilterCondition academyFilterCondition) {
if (academyFilterCondition.desiredMinAmount() != null && academyFilterCondition.desiredMaxAmount() != null) {
return " AND max_education_fee BETWEEN " + academyFilterCondition.desiredMinAmount() + " AND "
+ academyFilterCondition.desiredMaxAmount();
}
return "";
}

private String makeScroll(int pageNumber, int pageSize, String formattedQuery) {
int offset = pageNumber * pageSize;
formattedQuery += " ORDER BY a.academy_name LIMIT " + pageSize + " OFFSET " + offset;
return formattedQuery;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -32,4 +32,10 @@ AcademiesByLocationWithScroll findAcademiesByLocation(
Long memberId,
int pageNumber,
int pageSize);

AcademiesByFilterWithScroll filterAcademies(
AcademyFilterCondition academyFilterCondition,
Long memberId,
int pageNumber,
int pageSize);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package org.guzzing.studayserver.domain.academy.repository.dto;

import java.util.List;

public record AcademiesByFilterWithScroll (
List<AcademyByFilterWithScroll> academiesByLocation,
boolean hasNext
) {
public static AcademiesByFilterWithScroll of(
List<AcademyByFilterWithScroll> academiesByLocation,
boolean hasNext
) {
return new AcademiesByFilterWithScroll(
academiesByLocation,
hasNext
);
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package org.guzzing.studayserver.domain.academy.repository.dto;

public record AcademyByFilterWithScroll (
Long academyId,
String academyName,
String fullAddress,
String phoneNumber,
Double latitude,
Double longitude,
String shuttleAvailable,
boolean isLiked
) {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package org.guzzing.studayserver.domain.academy.repository.dto;

public record AcademyByLocationWithScroll(
Long academyId,
String academyName,
String fullAddress,
String phoneNumber,
Double latitude,
Double longitude,
String shuttleAvailable,
boolean isLiked
) {
}

0 comments on commit cfa1f87

Please sign in to comment.