diff --git a/src/main/java/makar/dev/converter/RouteConverter.java b/src/main/java/makar/dev/converter/RouteConverter.java index 35c7f86..69bc70e 100644 --- a/src/main/java/makar/dev/converter/RouteConverter.java +++ b/src/main/java/makar/dev/converter/RouteConverter.java @@ -5,7 +5,7 @@ import makar.dev.dto.response.RouteResponse; import java.util.ArrayList; -import java.util.Comparator; +import java.util.Collections; import java.util.List; import java.util.stream.Collectors; @@ -70,7 +70,8 @@ public static RouteResponse.BriefRouteDto toBriefRouteDto(Route route){ } public static List<RouteResponse.BriefRouteDtoWithRouteId> toBriefRouteDtoList(List<Route> routes){ - routes.sort(Comparator.comparingInt(Route::getRecentOrder).reversed()); + // recent_route_id가 큰 것부터 조회되도록(최신순) 리스트의 순서를 뒤집음 + Collections.reverse(routes); return routes.stream() .map(route -> diff --git a/src/main/java/makar/dev/domain/RecentRoute.java b/src/main/java/makar/dev/domain/RecentRoute.java new file mode 100644 index 0000000..c25a1b5 --- /dev/null +++ b/src/main/java/makar/dev/domain/RecentRoute.java @@ -0,0 +1,43 @@ +package makar.dev.domain; + +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.FetchType; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; +import jakarta.persistence.JoinColumn; +import jakarta.persistence.ManyToOne; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Getter +@AllArgsConstructor +@NoArgsConstructor +@Entity +public class RecentRoute { + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + @Column(name = "recent_route_id") + private Long id; + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "user_id") + private User user; + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "route_id") + private Route route; + + @Builder + public RecentRoute(User user, Route route) { + this.user = user; + this.route = route; + + // 객체 단에서 User의 최근 경로 리스트에 해당 RecentRoute를 넣어주는 + // 연관관계 편의메서드 + user.getRecentRouteList().add(this); + } +} diff --git a/src/main/java/makar/dev/domain/Route.java b/src/main/java/makar/dev/domain/Route.java index dd621bc..baefab7 100644 --- a/src/main/java/makar/dev/domain/Route.java +++ b/src/main/java/makar/dev/domain/Route.java @@ -35,15 +35,7 @@ public class Route { @Column(nullable = false) private List<SubRoute> subRouteList; - // 최근 경로 리스트 내 순서 - @Column(name = "recent_order") - private int recentOrder; - public void updateSchedule(Schedule schedule){ this.schedule = schedule; } - - public void setRecentOrder(int recentOrder) { - this.recentOrder = recentOrder; - } } diff --git a/src/main/java/makar/dev/domain/User.java b/src/main/java/makar/dev/domain/User.java index 142dea2..c446df0 100644 --- a/src/main/java/makar/dev/domain/User.java +++ b/src/main/java/makar/dev/domain/User.java @@ -6,10 +6,10 @@ import lombok.Getter; import lombok.NoArgsConstructor; import lombok.Setter; -import makar.dev.common.exception.GeneralException; -import makar.dev.common.status.ErrorStatus; +import java.util.ArrayList; import java.util.List; +import java.util.stream.Collectors; @Getter @Setter @@ -46,8 +46,8 @@ public class User { @OneToMany(cascade = CascadeType.ALL, mappedBy = "user") private List<Noti> notiList; //알림 설정 - @OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY) - private List<Route> recentRouteList; //최근 경로 리스트 + @OneToMany(mappedBy = "user", cascade = CascadeType.ALL) + private List<RecentRoute> recentRouteList = new ArrayList<>(); @OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY) private List<Route> favoriteRouteList; //즐겨찾는 경로 리스트 @@ -62,40 +62,17 @@ public User(String userName){ public boolean isFavoriteSchoolStationExist(){return this.favoriteSchoolStation != null;} public void addNotiList(Noti noti){this.notiList.add(noti);} public void addFavoriteRoute(Route route){this.favoriteRouteList.add(favoriteRouteList.size(), route);} - public void addRecentRouteList(Route route) { - int maxOrder = -1; - Route existingRoute = null; - - // 동일한 routeId를 가진 Route가 이미 최근 경로 리스트에 존재하는지 확인 - for (Route r : this.recentRouteList) { - if (r.getRouteId().equals(route.getRouteId())) { - existingRoute = r; - } - if (r.getRecentOrder() > maxOrder) { - maxOrder = r.getRecentOrder(); - } - } - - if (existingRoute != null) { - // 이미 리스트에 존재하는 경우 recentOrder만 수정 - existingRoute.setRecentOrder(maxOrder + 1); - } else { - // 최근 경로 리스트 사이즈 최대 5개 유지 - if (this.recentRouteList.size() >= 5) { - this.recentRouteList.remove(0); - } - - // 새로운 Route일 경우 리스트의 마지막에 추가 - route.setRecentOrder(maxOrder + 1); - this.recentRouteList.add(route); - } + // user의 최근 경로를 Route 타입의 List로 반환하는 함수 + public List<Route> findRecentRouteList() { + return this.recentRouteList.stream() + .map(RecentRoute::getRoute) + .collect(Collectors.toList()); } - public void removeRecentRouteList(Route route) { - boolean removed = this.recentRouteList.remove(route); - if (!removed) { - throw new GeneralException(ErrorStatus.NOT_FOUND_IN_RECENT_ROUTE_LIST); - } + // user의 최근 경로 리스트에서 특정 최근 경로 삭제 + public void removeRecentRoute(RecentRoute route) { + this.getRecentRouteList().remove(route); } + // user의 최근 경로 리스트 비우기 public void clearRecentRouteList() { this.recentRouteList.clear(); } diff --git a/src/main/java/makar/dev/repository/RecentRouteRepository.java b/src/main/java/makar/dev/repository/RecentRouteRepository.java new file mode 100644 index 0000000..cef45b4 --- /dev/null +++ b/src/main/java/makar/dev/repository/RecentRouteRepository.java @@ -0,0 +1,13 @@ +package makar.dev.repository; + +import makar.dev.domain.RecentRoute; +import makar.dev.domain.Route; +import makar.dev.domain.User; +import org.springframework.data.jpa.repository.JpaRepository; + +import java.util.Optional; + +public interface RecentRouteRepository extends JpaRepository<RecentRoute, Long> { + Optional<RecentRoute> findByUserAndRoute(User user, Route route); + void deleteByUser(User user); +} diff --git a/src/main/java/makar/dev/service/RouteService.java b/src/main/java/makar/dev/service/RouteService.java index ec0a018..c16fd9b 100644 --- a/src/main/java/makar/dev/service/RouteService.java +++ b/src/main/java/makar/dev/service/RouteService.java @@ -31,6 +31,7 @@ public class RouteService { private final ScheduleRepository scheduleRepository; private final UserRepository userRepository; private final NotiRepository notiRepository; + private final RecentRouteRepository recentRouteRepository; private final APIManager apiManager; private final MakarManager makarManager; private final TransferService transferService; @@ -67,8 +68,9 @@ public RouteResponse.RouteDto setRoute(Long userId, Long routeId){ user.addNotiList(makarNoti); user.addNotiList(getOffNoti); - // 해당 경로, 유저의 최근 경로 리스트에 저장 - user.addRecentRouteList(route); + // 해당 경로, 유저 정보를 갖는 RecentRoute 객체 생성 후 저장 + addRecentRoute(user, route); + return RouteConverter.toRouteDto(route); } @@ -315,11 +317,34 @@ private String getDestinationTime(String sourceTime, int totalTime) { return sdf.format(calendar.getTime()); } + // 특정 경로, 유저를 기반으로 하는 RecentRoute 객체 생성 후 저장 + @Transactional + public void addRecentRoute(User user, Route route) { + // 동일한 routeId를 가진 Route가 이미 최근 경로 리스트에 존재한다면 + // DB와 리스트에서 제거 + recentRouteRepository.findByUserAndRoute(user, route).ifPresent( + recentRoute -> { + recentRouteRepository.delete(recentRoute); + user.removeRecentRoute(recentRoute); + } + ); + + // 최근 경로 리스트 사이즈 최대 5개 유지 + if (user.getRecentRouteList().size() >= 5) { + RecentRoute recentRoute = user.getRecentRouteList().get(0); + recentRouteRepository.delete(recentRoute); + } + + // 새로운 RecentRoute 생성 및 저장 + RecentRoute newRecentRoute = new RecentRoute(user, route); + recentRouteRepository.save(newRecentRoute); + } + // 최근 경로 리스트 조회하기 public RouteResponse.RecentRouteListDto getAllRecentRoute(Long userId) { User user = findUserById(userId); return RouteResponse.RecentRouteListDto.builder() - .recentRouteList(RouteConverter.toBriefRouteDtoList(user.getRecentRouteList())) + .recentRouteList(RouteConverter.toBriefRouteDtoList(user.findRecentRouteList())) .build(); } @@ -328,13 +353,18 @@ public RouteResponse.RecentRouteListDto getAllRecentRoute(Long userId) { public void deleteRecentRoute(Long userId, Long routeId) { User user = findUserById(userId); Route route = findRouteById(routeId); - user.removeRecentRouteList(route); + RecentRoute recentRoute = recentRouteRepository.findByUserAndRoute(user, route).orElseThrow( + () -> new GeneralException(ErrorStatus.NOT_FOUND_IN_RECENT_ROUTE_LIST) + ); + recentRouteRepository.delete(recentRoute); + user.removeRecentRoute(recentRoute); } // 모든 최근 경로 삭제 @Transactional public void deleteAllRecentRoute(Long userId) { User user = findUserById(userId); + recentRouteRepository.deleteByUser(user); user.clearRecentRouteList(); } }