Skip to content
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
1 change: 1 addition & 0 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ subprojects {

// Test
testImplementation 'org.springframework.boot:spring-boot-starter-test'
testImplementation 'com.h2database:h2'

// Actuator
implementation 'org.springframework.boot:spring-boot-starter-actuator'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -80,12 +80,9 @@ public void enrollDiary(String socialId, String imageUrl, String title) {

@Transactional
public void createNextDayDiaries(LocalDate nextDay) {
List<User> allUser = userRetriever.getAllUsers();
for (User user : allUser) {
if (diaryRetriever.existsDiary(user, nextDay)) {
continue;
}
diaryModifier.createDiary(nextDay, user);
List<User> allUser = userRetriever.getAllUsersWithoutDiary(nextDay);
for (User u : allUser) {
diaryModifier.createDiary(nextDay, u);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,15 @@
import com.fourcut.diary.notification.domain.Notification;
import com.fourcut.diary.user.domain.User;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;

import java.util.List;
import java.util.Optional;

public interface NotificationRepository extends JpaRepository<Notification, Long> {

Optional<Notification> findByUser(User user);

@Query("SELECT DISTINCT n FROM Notification n JOIN FETCH n.user")
List<Notification> findAllWithUser();
}
Original file line number Diff line number Diff line change
Expand Up @@ -37,4 +37,8 @@ public Notification getTodayNotification(User user) {
public List<Notification> getAllNotifications() {
return notificationRepository.findAll();
}

public List<Notification> getAllNotificationsWithUser() {
return notificationRepository.findAllWithUser();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ public PictureCaptureInfoDto getTakePictureInfoByUser(String socialId) {

@Transactional
public void updateNotificationTime(LocalDate nextDay) {
List<Notification> notifications = notificationRetriever.getAllNotifications();
List<Notification> notifications = notificationRetriever.getAllNotificationsWithUser();
notifications.forEach(notification -> {
List<LocalDateTime> timeSlots = NotificationTimeSlotUtil.getRandomTimeSlot(notification.getUser(), nextDay);
notificationModifier.updateNextDayNotificationTime(notification, timeSlots);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
package com.fourcut.diary.user.repository;

import com.fourcut.diary.user.domain.User;
import io.lettuce.core.dynamic.annotation.Param;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;

import java.time.LocalDate;
import java.util.List;
import java.util.Optional;

public interface UserRepository extends JpaRepository<User, Long>, UserRepositoryCustom {
Expand All @@ -13,6 +17,18 @@ public interface UserRepository extends JpaRepository<User, Long>, UserRepositor
boolean existsBySocialId(String socialId);
Optional<User> findBySocialId(String socialId);

@Query("""
SELECT u\s
FROM User u\s
WHERE NOT EXISTS (
SELECT 1\s
FROM Diary d\s
WHERE d.user = u\s
AND d.date = :nextDay
)
\s""")
List<User> findAllWithoutDiaryOn(@Param("nextDay") LocalDate nextDay);

// UPDATE

// DELETE
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Component;

import java.time.LocalTime;
import java.time.LocalDate;
import java.util.List;

@Component
Expand All @@ -34,7 +34,7 @@ public void checkExistUser(String socialId) {
}
}

public List<User> getAllUsers() {
return userRepository.findAll();
public List<User> getAllUsersWithoutDiary(LocalDate nextDay) {
return userRepository.findAllWithoutDiaryOn(nextDay);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
package com.fourcut.diary.service;

import com.fourcut.diary.diary.service.DiaryService;
import com.fourcut.diary.notification.domain.Notification;
import com.fourcut.diary.notification.repository.NotificationRepository;
import com.fourcut.diary.notification.service.NotificationService;
import com.fourcut.diary.user.domain.User;
import com.fourcut.diary.user.repository.UserRepository;
import jakarta.persistence.EntityManager;
import jakarta.persistence.EntityManagerFactory;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.stat.Statistics;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.ActiveProfiles;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.IntStream;

@SpringBootTest
@Transactional
@ActiveProfiles("test")
public class SchedulerServiceQueryCountTest {

@Autowired
private EntityManagerFactory emf;

@Autowired
private EntityManager em;

@Autowired
private SchedulerService schedulerService;

@Autowired
private DiaryService diaryService;

@Autowired
private NotificationService notificationService;

@Autowired
private UserRepository userRepository;

@Autowired
private NotificationRepository notificationRepository;

private final LocalDate nextDay = LocalDate.now();

@BeforeEach
void setUpDummyDataAndEnableStats() {
SessionFactoryImplementor sf = emf.unwrap(SessionFactoryImplementor.class);
sf.getStatistics().setStatisticsEnabled(true);

notificationRepository.deleteAll();
userRepository.deleteAll();
em.flush(); em.clear();

List<User> users = IntStream.rangeClosed(1, 1000)
.mapToObj(i -> com.fourcut.diary.user.domain.User.newInstance(
"social" + i,
"nick" + i,
LocalDate.of(1990, 1, 1),
com.fourcut.diary.user.domain.Gender.MALE,
LocalTime.of(8, 0),
LocalTime.of(20, 0),
"arn" + i,
"token" + i
))
.collect(Collectors.toList());
userRepository.saveAll(users);
em.flush(); em.clear();

List<Notification> notis = users.stream()
.map(u -> {
List<LocalDateTime> slots = Arrays.asList(
nextDay.atTime( 9, 0),
nextDay.atTime(12, 0),
nextDay.atTime(15, 0),
nextDay.atTime(18, 0)
);

return Notification.builder()
.firstTimeSlot (slots.get(0))
.secondTimeSlot(slots.get(1))
.thirdTimeSlot (slots.get(2))
.fourthTimeSlot(slots.get(3))
.user(u)
.build();
})
.collect(Collectors.toList());
notificationRepository.saveAll(notis);
em.flush(); em.clear();
}

@Test
void countQueriesCreateNextDayDiaries() {
Statistics stats = emf.unwrap(SessionFactoryImplementor.class).getStatistics();
stats.clear();

diaryService.createNextDayDiaries(nextDay);
em.flush();

long q = stats.getPrepareStatementCount();
System.out.println("createNextDayDiaries 쿼리 수: " + q);
}

@Test
void countQueriesUpdateNotificationTime() {
Statistics stats = emf.unwrap(SessionFactoryImplementor.class).getStatistics();
stats.clear();

notificationService.updateNotificationTime(nextDay);
em.flush();

long q = stats.getPrepareStatementCount();
System.out.println("updateNotificationTime 쿼리 수: " + q);
}
}

19 changes: 19 additions & 0 deletions module-notification/src/test/resources/application-test.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
spring:
datasource:
url: jdbc:h2:mem:testdb;DB_CLOSE_DELAY=-1;MODE=MySQL
driver-class-name: org.h2.Driver
username: sa
password:

jpa:
hibernate:
ddl-auto: create-drop
properties:
hibernate:
dialect: org.hibernate.dialect.H2Dialect
globally_quoted_identifiers: true

logging:
level:
org.hibernate.SQL: DEBUG
org.hibernate.type.descriptor.sql.BasicBinder: TRACE