Skip to content

Commit

Permalink
Merge pull request #63 from kakao-tech-campus-2nd-step3/feat/#7-place
Browse files Browse the repository at this point in the history
[refacotr] #7 QueryDsl을 적용했어요
  • Loading branch information
sanghee0820 authored Oct 14, 2024
2 parents 2523396 + 397b4fe commit f0404b4
Show file tree
Hide file tree
Showing 9 changed files with 191 additions and 220 deletions.
18 changes: 11 additions & 7 deletions src/main/java/team7/inplace/global/queryDsl/QueryDslConfig.java
Original file line number Diff line number Diff line change
@@ -1,16 +1,20 @@
package team7.inplace.global.queryDsl;

import com.querydsl.jpa.impl.JPAQueryFactory;
import jakarta.persistence.EntityManager;
import jakarta.persistence.PersistenceContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class QueryDslConfig {

// @PersistenceContext
// private EntityManager entityManager;
//
// @Bean
// public JPAQueryFactory jpaQueryFactory() {
// return new JPAQueryFactory(entityManager);
// }
@PersistenceContext
private EntityManager entityManager;

@Bean
public JPAQueryFactory jpaQueryFactory() {
return new JPAQueryFactory(entityManager);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ private Page<Place> getPlacesByDistance(
List<String> categoryFilters,
List<String> influencerFilters
) {
return placeRepository.getPlacesByDistanceAndFilters(
return placeRepository.findPlacesByDistanceAndFilters(
placesCoordinateCommand.topLeftLongitude(),
placesCoordinateCommand.topLeftLatitude(),
placesCoordinateCommand.bottomRightLongitude(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,15 +50,15 @@ public record MenuInfos(

public static MenuInfos of(List<Menu> menus) {
List<MenuInfo> menuList = menus.stream()
.map(menu -> new MenuInfo(Integer.parseInt(menu.getPrice()), menu.isRecommend(),
.map(menu -> new MenuInfo(menu.getPrice(), menu.isRecommend(),
menu.getMenuName(), menu.getMenuImgUrl(), menu.getDescription()))
.toList();

return new MenuInfos(menuList, LocalDateTime.now());
}

public record MenuInfo(
Integer price,
String price,
Boolean recommend,
String menuName,
String menuImgUrl,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,21 +1,27 @@
package team7.inplace.place.persistence;

import java.util.List;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.repository.query.Param;
import team7.inplace.place.domain.Place;

public interface PlaceCustomRepository {

// Page<Place> findPlacesByDistance(
// @Param("longitude") String longitude,
// @Param("latitude") String latitude,
// Pageable pageable);
//
// Page<Place> findPlacesByDistanceAndFilters(
// @Param("topLeftLongitude") String topLeftLongitude,
// @Param("topLeftLatitude") String topLeftLatitude,
// @Param("bottomRightLongitude") String bottomRightLongitude,
// @Param("bottomRightLatitude") String bottomRightLatitude,
// @Param("longitude") String longitude,
// @Param("latitude") String latitude,
// @Param("categories") List<String> categories,
// @Param("influencers") List<String> influencers,
// Pageable pageable);
Page<Place> findPlacesByDistance(
@Param("longitude") String longitude,
@Param("latitude") String latitude,
Pageable pageable);

Page<Place> findPlacesByDistanceAndFilters(
@Param("topLeftLongitude") String topLeftLongitude,
@Param("topLeftLatitude") String topLeftLatitude,
@Param("bottomRightLongitude") String bottomRightLongitude,
@Param("bottomRightLatitude") String bottomRightLatitude,
@Param("longitude") String longitude,
@Param("latitude") String latitude,
@Param("categories") List<String> categories,
@Param("influencers") List<String> influencers,
Pageable pageable);

}
Original file line number Diff line number Diff line change
@@ -1,94 +1,111 @@
package team7.inplace.place.persistence;

//@Repository
//@AllArgsConstructor
import com.querydsl.core.types.dsl.BooleanExpression;
import com.querydsl.core.types.dsl.Expressions;
import com.querydsl.core.types.dsl.NumberTemplate;
import com.querydsl.jpa.impl.JPAQueryFactory;
import java.util.List;
import java.util.stream.Collectors;
import lombok.AllArgsConstructor;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Repository;
import team7.inplace.influencer.domain.QInfluencer;
import team7.inplace.place.domain.Category;
import team7.inplace.place.domain.Place;
import team7.inplace.place.domain.QPlace;
import team7.inplace.video.domain.QVideo;

@Repository
@AllArgsConstructor
public class PlaceCustomRepositoryImpl implements PlaceCustomRepository {

// private final JPAQueryFactory jpaQueryFactory;
//
// @Override
// public Page<Place> findPlacesByDistance(String longitude, String latitude, Pageable pageable) {
// QPlace place = QPlace.place;
//
// NumberTemplate<Double> distanceExpression = Expressions.numberTemplate(Double.class,
// "6371 * acos(cos(radians({0})) * cos(radians({1})) * cos(radians({2}) - radians({3})) + sin(radians({0})) * sin(radians({1})))",
// Double.parseDouble(latitude), place.coordinate.latitude, place.coordinate.longitude,
// Double.parseDouble(longitude));
//
// List<Place> places = jpaQueryFactory.selectFrom(place)
// .orderBy(distanceExpression.asc())
// .offset(pageable.getOffset())
// .limit(pageable.getPageSize())
// .fetch();
//
// return new PageImpl<>(places, pageable, places.size());
// }
//
// @Override
// public Page<Place> findPlacesByDistanceAndFilters(String topLeftLongitude,
// String topLeftLatitude, String bottomRightLongitude, String bottomRightLatitude,
// String longitude, String latitude, List<String> categories, List<String> influencers,
// Pageable pageable) {
//
// QPlace place = QPlace.place;
// QVideo video = QVideo.video;
// QInfluencer influencer = QInfluencer.influencer;
//
// NumberTemplate<Double> distanceExpression = Expressions.numberTemplate(Double.class,
// "6371 * acos(cos(radians({0})) * cos(radians({1})) * cos(radians({2}) - radians({3})) + sin(radians({0})) * sin(radians({1})))",
// Double.parseDouble(latitude), place.coordinate.latitude, place.coordinate.longitude,
// Double.parseDouble(longitude));
//
// List<Place> places = jpaQueryFactory.selectFrom(place)
// .leftJoin(video).on(video.place.eq(place))
// .leftJoin(place).on(influencer.id.eq(video.influencer.id))
// .where(
// withinBoundary(
// place,
// Double.parseDouble(topLeftLongitude),
// Double.parseDouble(topLeftLatitude),
// Double.parseDouble(bottomRightLongitude),
// Double.parseDouble(bottomRightLatitude)
// ),
// placeCategoryIn(categories),
// placeInfluencerIn(influencers)
// ).orderBy(distanceExpression.asc())
// .offset(pageable.getOffset())
// .limit(pageable.getPageSize())
// .fetch();
//
// return new PageImpl<>(places, pageable, places.size());
// }
//
// private BooleanExpression withinBoundary(QPlace place, double topLeftLongitude,
// double topLeftLatitude,
// double bottomRightLongitude, double bottomRightLatitude) {
// NumberTemplate<Double> longitude = Expressions.numberTemplate(Double.class,
// "CAST({0} AS DOUBLE)", place.coordinate.longitude);
// NumberTemplate<Double> latitude = Expressions.numberTemplate(Double.class,
// "CAST({0} AS DOUBLE)", place.coordinate.latitude);
//
// return longitude.between(topLeftLongitude, bottomRightLongitude)
// .and(latitude.between(bottomRightLatitude, topLeftLatitude));
// }
//
// private BooleanExpression placeCategoryIn(List<String> categories) {
// if (categories == null) {
// return null;
// }
//
// List<Category> enumCategories = categories.stream()
// .map(Category::valueOf)
// .collect(Collectors.toList());
//
// return QPlace.place.category.in(enumCategories);
// }
//
// private BooleanExpression placeInfluencerIn(List<String> influencers) {
// if (influencers == null) {
// return null;
// }
//
// return QInfluencer.influencer.name.in(influencers);
// }
private final JPAQueryFactory jpaQueryFactory;

@Override
public Page<Place> findPlacesByDistance(String longitude, String latitude, Pageable pageable) {
QPlace place = QPlace.place;

NumberTemplate<Double> distanceExpression = Expressions.numberTemplate(Double.class,
"6371 * acos(cos(radians({0})) * cos(radians(CAST({1} AS DOUBLE))) * cos(radians(CAST({2} AS DOUBLE)) - radians({3})) + sin(radians({0})) * sin(radians(CAST({1} AS DOUBLE))))",
Double.parseDouble(latitude), place.coordinate.latitude, place.coordinate.longitude,
Double.parseDouble(longitude));

List<Place> places = jpaQueryFactory.selectFrom(place)
.orderBy(distanceExpression.asc())
.offset(pageable.getOffset())
.limit(pageable.getPageSize())
.fetch();

return new PageImpl<>(places, pageable, places.size());
}

@Override
public Page<Place> findPlacesByDistanceAndFilters(String topLeftLongitude,
String topLeftLatitude, String bottomRightLongitude, String bottomRightLatitude,
String longitude, String latitude, List<String> categories, List<String> influencers,
Pageable pageable) {

QPlace place = QPlace.place;
QVideo video = QVideo.video;
QInfluencer influencer = QInfluencer.influencer;

NumberTemplate<Double> distanceExpression = Expressions.numberTemplate(Double.class,
"6371 * acos(cos(radians({0})) * cos(radians(CAST({1} AS DOUBLE))) * cos(radians(CAST({2} AS DOUBLE)) - radians({3})) + sin(radians({0})) * sin(radians(CAST({1} AS DOUBLE))))",
Double.parseDouble(latitude), place.coordinate.latitude, place.coordinate.longitude,
Double.parseDouble(longitude));

List<Place> places = jpaQueryFactory.selectFrom(place)
.leftJoin(video).on(video.place.eq(place))
.leftJoin(influencer).on(video.influencer.eq(influencer))
.where(
withinBoundary(
place,
Double.parseDouble(topLeftLongitude),
Double.parseDouble(topLeftLatitude),
Double.parseDouble(bottomRightLongitude),
Double.parseDouble(bottomRightLatitude)
),
placeCategoryIn(categories),
placeInfluencerIn(influencers)
).orderBy(distanceExpression.asc())
.offset(pageable.getOffset())
.limit(pageable.getPageSize())
.fetch();

return new PageImpl<>(places, pageable, places.size());
}

private BooleanExpression withinBoundary(QPlace place, double topLeftLongitude,
double topLeftLatitude,
double bottomRightLongitude, double bottomRightLatitude) {
NumberTemplate<Double> longitude = Expressions.numberTemplate(Double.class,
"CAST({0} AS DOUBLE)", place.coordinate.longitude);
NumberTemplate<Double> latitude = Expressions.numberTemplate(Double.class,
"CAST({0} AS DOUBLE)", place.coordinate.latitude);

return longitude.between(topLeftLongitude, bottomRightLongitude)
.and(latitude.between(bottomRightLatitude, topLeftLatitude));
}

private BooleanExpression placeCategoryIn(List<String> categories) {
if (categories == null) {
return null;
}

List<Category> enumCategories = categories.stream()
.map(Category::of) // Category.of() 메서드로 직접 매핑
.collect(Collectors.toList());

return QPlace.place.category.in(enumCategories);
}

private BooleanExpression placeInfluencerIn(List<String> influencers) {
if (influencers == null) {
return null;
}

return QInfluencer.influencer.name.in(influencers);
}
}
Original file line number Diff line number Diff line change
@@ -1,68 +1,10 @@
package team7.inplace.place.persistence;

import java.util.List;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;
import org.springframework.stereotype.Repository;
import team7.inplace.place.domain.Place;

@Repository
public interface PlaceRepository extends JpaRepository<Place, Long> {
public interface PlaceRepository extends JpaRepository<Place, Long>, PlaceCustomRepository {

//거리 계산
@Query(value = "SELECT *, " +
"(6371 * acos(cos(radians(CAST(:latitude AS DECIMAL(10, 6)))) " +
"* cos(radians(CAST(latitude AS DECIMAL(10, 6)))) " +
"* cos(radians(CAST(longitude AS DECIMAL(10, 6))) - radians(CAST(:longitude AS DECIMAL(10, 6)))) "
+
"+ sin(radians(CAST(:latitude AS DECIMAL(10, 6)))) " +
"* sin(radians(CAST(latitude AS DECIMAL(10, 6)))))) AS distance " +
"FROM places " +
"ORDER BY distance",
countQuery = "SELECT count(*) FROM places", // 총 개수 쿼리
nativeQuery = true)
Page<Place> getPlacesByDistance(
@Param("longitude") String longitude,
@Param("latitude") String latitude,
Pageable pageable);

@Query(value = "SELECT p.*, " +
"(6371 * acos(cos(radians(CAST(:latitude AS DECIMAL(10, 6)))) " +
"* cos(radians(CAST(p.latitude AS DECIMAL(10, 6)))) " +
"* cos(radians(CAST(p.longitude AS DECIMAL(10, 6))) - radians(CAST(:longitude AS DECIMAL(10, 6)))) "
+
"+ sin(radians(CAST(:latitude AS DECIMAL(10, 6)))) " +
"* sin(radians(CAST(p.latitude AS DECIMAL(10, 6)))))) AS distance " +
"FROM places p " +
"LEFT JOIN video v ON p.id = v.place_id " +
"LEFT JOIN influencer i ON v.influencer_id = i.id " +
"WHERE (:categories IS NULL OR p.category IN (:categories)) " +
"AND (:influencers IS NULL OR i.name IN (:influencers)) " +
"AND (CAST(p.longitude AS DECIMAL(10, 6)) BETWEEN CAST(:topLeftLongitude AS DECIMAL(10, 6)) AND CAST(:bottomRightLongitude AS DECIMAL(10, 6))) "
+
"AND (CAST(p.latitude AS DECIMAL(10, 6)) BETWEEN CAST(:bottomRightLatitude AS DECIMAL(10, 6)) AND CAST(:topLeftLatitude AS DECIMAL(10, 6)))"
+
"ORDER BY distance",
countQuery = "SELECT count(*) FROM places p " +
"LEFT JOIN video v ON p.id = v.place_id " +
"LEFT JOIN influencer i ON v.influencer_id = i.id " +
"WHERE (:categories IS NULL OR p.category IN (:categories)) " +
"AND (:influencers IS NULL OR i.name IN (:influencers)) " +
"AND (CAST(p.longitude AS DECIMAL(10, 6)) BETWEEN CAST(:topLeftLongitude AS DECIMAL(10, 6)) AND CAST(:bottomRightLongitude AS DECIMAL(10, 6))) "
+
"AND (CAST(p.latitude AS DECIMAL(10, 6)) BETWEEN CAST(:bottomRightLatitude AS DECIMAL(10, 6)) AND CAST(:topLeftLatitude AS DECIMAL(10, 6)))",
nativeQuery = true)
Page<Place> getPlacesByDistanceAndFilters(
@Param("topLeftLongitude") String topLeftLongitude,
@Param("topLeftLatitude") String topLeftLatitude,
@Param("bottomRightLongitude") String bottomRightLongitude,
@Param("bottomRightLatitude") String bottomRightLatitude,
@Param("longitude") String longitude,
@Param("latitude") String latitude,
@Param("categories") List<String> categories,
@Param("influencers") List<String> influencers,
Pageable pageable);
}
Loading

0 comments on commit f0404b4

Please sign in to comment.