-
Notifications
You must be signed in to change notification settings - Fork 17
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
여행 생성 및 여행 상세 조회 쿼리 개선 #651
Changes from 11 commits
82186ed
a172e46
70ff2c3
3e9a3be
899b2af
7b6b60c
de40180
4d464e9
b8f9432
033e403
a23f0b9
d3ab7a8
f812570
75c3a7c
1b1a4c6
f5ea739
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,7 +1,25 @@ | ||
package hanglog.city.domain.repository; | ||
|
||
import hanglog.city.domain.City; | ||
import java.util.List; | ||
import org.springframework.data.jpa.repository.JpaRepository; | ||
import org.springframework.data.jpa.repository.Query; | ||
import org.springframework.data.repository.query.Param; | ||
|
||
public interface CityRepository extends JpaRepository<City, Long> { | ||
|
||
@Query(""" | ||
SELECT c | ||
FROM City c | ||
WHERE c.id in :ids | ||
""") | ||
List<City> findCitiesByIds(@Param("ids") final List<Long> ids); | ||
|
||
@Query(""" | ||
SELECT c | ||
FROM City c, TripCity tc | ||
WHERE c.id = tc.city.id | ||
AND tc.trip.id = :tripId | ||
""") | ||
List<City> findCitiesByTripId(@Param("tripId") final Long tripId); | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
package hanglog.global.detector; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 쿼리 카운터 이 pr에서 넣기로 한건가요? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. i want... There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||
|
||
import jakarta.annotation.Nonnull; | ||
import jakarta.annotation.Nullable; | ||
import lombok.RequiredArgsConstructor; | ||
import org.aopalliance.intercept.MethodInterceptor; | ||
import org.aopalliance.intercept.MethodInvocation; | ||
import org.springframework.aop.framework.ProxyFactory; | ||
|
||
@RequiredArgsConstructor | ||
public class ConnectionProxyHandler implements MethodInterceptor { | ||
|
||
private static final String JDBC_PREPARE_STATEMENT_METHOD_NAME = "prepareStatement"; | ||
|
||
private final Object connection; | ||
private final LoggingForm loggingForm; | ||
|
||
@Nullable | ||
@Override | ||
public Object invoke(@Nonnull final MethodInvocation invocation) throws Throwable { | ||
final Object result = invocation.proceed(); | ||
|
||
if (hasConnection(result) && hasPreparedStatementInvoked(invocation)) { | ||
final ProxyFactory proxyFactory = new ProxyFactory(result); | ||
proxyFactory.addAdvice(new PreparedStatementProxyHandler(loggingForm)); | ||
return proxyFactory.getProxy(); | ||
} | ||
|
||
return result; | ||
} | ||
|
||
private boolean hasPreparedStatementInvoked(final MethodInvocation invocation) { | ||
return invocation.getMethod().getName().equals(JDBC_PREPARE_STATEMENT_METHOD_NAME); | ||
} | ||
|
||
private boolean hasConnection(final Object result) { | ||
return result != null; | ||
} | ||
|
||
public Object getProxy() { | ||
final ProxyFactory proxyFactory = new ProxyFactory(connection); | ||
proxyFactory.addAdvice(this); | ||
return proxyFactory.getProxy(); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
package hanglog.global.detector; | ||
|
||
import lombok.Getter; | ||
import lombok.ToString; | ||
|
||
@Getter | ||
@ToString | ||
public class LoggingForm { | ||
|
||
private String apiUrl; | ||
private String apiMethod; | ||
private Long queryCounts = 0L; | ||
private Long queryTime = 0L; | ||
|
||
public void queryCountUp() { | ||
queryCounts++; | ||
} | ||
|
||
public void addQueryTime(final Long queryTime) { | ||
this.queryTime += queryTime; | ||
} | ||
|
||
public void setApiUrl(final String apiUrl) { | ||
this.apiUrl = apiUrl; | ||
} | ||
|
||
public void setApiMethod(final String apiMethod) { | ||
this.apiMethod = apiMethod; | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
package hanglog.global.detector; | ||
|
||
import jakarta.annotation.Nonnull; | ||
import jakarta.annotation.Nullable; | ||
import java.lang.reflect.Method; | ||
import java.util.List; | ||
import lombok.RequiredArgsConstructor; | ||
import org.aopalliance.intercept.MethodInterceptor; | ||
import org.aopalliance.intercept.MethodInvocation; | ||
|
||
@RequiredArgsConstructor | ||
public class PreparedStatementProxyHandler implements MethodInterceptor { | ||
|
||
private static final List<String> JDBC_QUERY_METHOD = | ||
List.of("executeQuery", "execute", "executeUpdate"); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 줄바꿈..뭔가 묘하게 불편한데..List.of를 붙이고 안에 내용을 한줄에 하나씩으로 띄우는거 어떨까요 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||
|
||
private final LoggingForm loggingForm; | ||
|
||
@Nullable | ||
@Override | ||
public Object invoke(@Nonnull final MethodInvocation invocation) throws Throwable { | ||
|
||
final Method method = invocation.getMethod(); | ||
|
||
if (JDBC_QUERY_METHOD.contains(method.getName())) { | ||
final long startTime = System.currentTimeMillis(); | ||
final Object result = invocation.proceed(); | ||
final long endTime = System.currentTimeMillis(); | ||
|
||
loggingForm.addQueryTime(endTime - startTime); | ||
loggingForm.queryCountUp(); | ||
|
||
return result; | ||
} | ||
|
||
return invocation.proceed(); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
package hanglog.global.detector; | ||
|
||
import jakarta.servlet.http.HttpServletRequest; | ||
import lombok.extern.slf4j.Slf4j; | ||
import org.aspectj.lang.ProceedingJoinPoint; | ||
import org.aspectj.lang.annotation.After; | ||
import org.aspectj.lang.annotation.Around; | ||
import org.aspectj.lang.annotation.Aspect; | ||
import org.springframework.stereotype.Component; | ||
import org.springframework.web.context.request.RequestContextHolder; | ||
import org.springframework.web.context.request.ServletRequestAttributes; | ||
|
||
@Aspect | ||
@Slf4j | ||
@Component | ||
public class QueryCounterAop { | ||
private final ThreadLocal<LoggingForm> currentLoggingForm; | ||
|
||
public QueryCounterAop() { | ||
this.currentLoggingForm = new ThreadLocal<>(); | ||
} | ||
|
||
@Around("execution( * javax.sql.DataSource.getConnection())") | ||
public Object captureConnection(final ProceedingJoinPoint joinPoint) throws Throwable { | ||
final Object connection = joinPoint.proceed(); | ||
|
||
return new ConnectionProxyHandler(connection, getCurrentLoggingForm()).getProxy(); | ||
} | ||
|
||
private LoggingForm getCurrentLoggingForm() { | ||
if (currentLoggingForm.get() == null) { | ||
currentLoggingForm.set(new LoggingForm()); | ||
} | ||
|
||
return currentLoggingForm.get(); | ||
} | ||
|
||
@After("within(@org.springframework.web.bind.annotation.RestController *)") | ||
public void loggingAfterApiFinish() { | ||
final LoggingForm loggingForm = getCurrentLoggingForm(); | ||
|
||
ServletRequestAttributes attributes = | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 얜 final 아니에용? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||
(ServletRequestAttributes) RequestContextHolder.getRequestAttributes(); | ||
|
||
if (isInRequestScope(attributes)) { | ||
HttpServletRequest request = attributes.getRequest(); | ||
|
||
loggingForm.setApiMethod(request.getMethod()); | ||
loggingForm.setApiUrl(request.getRequestURI()); | ||
} | ||
|
||
log.info("{}", getCurrentLoggingForm()); | ||
currentLoggingForm.remove(); | ||
} | ||
|
||
private boolean isInRequestScope(final ServletRequestAttributes attributes) { | ||
return attributes != null; | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -10,11 +10,13 @@ public class RequestLoggingFilter extends AbstractRequestLoggingFilter { | |
|
||
@Override | ||
protected void beforeRequest(@NonNull final HttpServletRequest request, @NonNull final String message) { | ||
logger.info(message); | ||
if (!message.contains("prometheus")) { | ||
logger.info(message); | ||
} | ||
Comment on lines
+13
to
+15
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 오 ㅋㅋㅋ 👍 👍 👍 👍 👍 |
||
} | ||
|
||
@Override | ||
protected void afterRequest(@NonNull final HttpServletRequest request, @NonNull final String message) { | ||
logger.info(message); | ||
// logger.info(message); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 주석 처리하지말고 그냥 지우는건 어떤가요? |
||
} | ||
} |
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
|
@@ -16,7 +16,9 @@ | |||||
import jakarta.persistence.OrderBy; | ||||||
import java.time.LocalDate; | ||||||
import java.util.ArrayList; | ||||||
import java.util.HashSet; | ||||||
import java.util.List; | ||||||
import java.util.Set; | ||||||
import lombok.Getter; | ||||||
import lombok.NoArgsConstructor; | ||||||
import org.hibernate.annotations.SQLDelete; | ||||||
|
@@ -47,7 +49,7 @@ public class DayLog extends BaseEntity { | |||||
|
||||||
@OneToMany(mappedBy = "dayLog", cascade = REMOVE, orphanRemoval = true) | ||||||
@OrderBy(value = "ordinal ASC") | ||||||
private List<Item> items = new ArrayList<>(); | ||||||
private Set<Item> items = new HashSet<>(); | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
아이템 순서도 보장하게 LinkedHashSet을 사용하는건 어떤가요? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 순서는 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 내부적으로 LinkedHashSet으로 처리한다면, 어떤 부분에서 성능이 다른가용 ?? 갖고 있을 때 메모리를 더 잡아먹는다 ?? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
저도 홍고와 라온 말처럼 명시적으로 혹은 혹시 모를 버그를 방지하기 위한 LinkedHashSet으로 할당하는 것에 한표 하겠습니다. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 성능 차이는 일반 List와 LinkedList의 차이와 같습니다.! 그리고 명시적으로 라는 부분도 잘 모르곘는게, 그런데 DayLog의 Items는 다르다고 생각합니다. 그으으으런데 홍고의 말대로 |
||||||
|
||||||
public DayLog( | ||||||
final Long id, | ||||||
|
@@ -60,7 +62,7 @@ public DayLog( | |||||
this.title = title; | ||||||
this.ordinal = ordinal; | ||||||
this.trip = trip; | ||||||
this.items = items; | ||||||
this.items = new HashSet<>(items); | ||||||
} | ||||||
|
||||||
public DayLog( | ||||||
|
@@ -83,4 +85,12 @@ public LocalDate calculateDate() { | |||||
final LocalDate startDate = trip.getStartDate(); | ||||||
return startDate.plusDays((long) ordinal - DEFAULT_DAY); | ||||||
} | ||||||
|
||||||
public void addItem(final Item item) { | ||||||
items.add(item); | ||||||
} | ||||||
|
||||||
public List<Item> getItems() { | ||||||
return new ArrayList<>(items); | ||||||
} | ||||||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
package hanglog.trip.domain.repository; | ||
|
||
import hanglog.trip.domain.DayLog; | ||
import java.util.List; | ||
|
||
public interface CustomDayLogRepository { | ||
|
||
void saveAll(final List<DayLog> dayLogs); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
이거 사용이 안되고 있는것 같습니다.