Skip to content

Commit

Permalink
Merge pull request #46 from CAUSOLDOUTMEN/feature/44-feat-redis
Browse files Browse the repository at this point in the history
Feat: RedisCache를 통한 캐싱 적용 (#44) [잔여 부분]
  • Loading branch information
synoti21 authored Nov 2, 2023
2 parents c602883 + 8042863 commit 5895213
Show file tree
Hide file tree
Showing 9 changed files with 58 additions and 31 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -49,8 +49,8 @@ public ApiResponse<Void> updateFood(UpdateFoodDto updateFoodDto){
//음식 삭제
@Operation(summary = "[음식] 음식 정보 삭제",description = "음식에 대한 정보를 삭제합니다.")
@DeleteMapping("/{foodId}/delete")
public ApiResponse<Void> deleteFood(@PathVariable Long foodId){
foodService.deleteFood(foodId);
public ApiResponse<Void> deleteFood(@PathVariable Long foodId, @RequestHeader Long userId){
foodService.deleteFood(foodId, userId);
return ApiResponse.success(null, ResponseCode.FOOD_DELETE_SUCCESS.getMessage());
}

Expand Down Expand Up @@ -79,8 +79,8 @@ public ApiResponse<Void> updateFavoriteFood(UpdateFavoriteFoodDto updateFavorite
//즐겨찾기 음식 해제
@Operation(summary = "[즐겨찾기] 즐겨찾기 해제",description = "유저의 즐겨찾기에 등록된 음식을 해제합니다.")
@DeleteMapping("/favorite/{favoriteFoodId}")
public ApiResponse<Void> deleteFavoriteFood(@PathVariable Long favoriteFoodId){
foodService.deleteFavoriteFood(favoriteFoodId);
public ApiResponse<Void> deleteFavoriteFood(@PathVariable Long favoriteFoodId, @RequestHeader Long userId){
foodService.deleteFavoriteFood(favoriteFoodId, userId);
return ApiResponse.success(null, ResponseCode.FOOD_FAVORITE_DELETE_SUCCESS.getMessage());
}

Expand Down
7 changes: 5 additions & 2 deletions src/main/java/com/diareat/diareat/food/dto/CreateFoodDto.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
import lombok.Getter;
import lombok.NoArgsConstructor;

import java.time.LocalDate;

@Getter
@NoArgsConstructor
@AllArgsConstructor
Expand All @@ -13,8 +15,9 @@ public class CreateFoodDto {
private Long userId;
private String name;
private BaseNutrition baseNutrition;
private LocalDate date;

public static CreateFoodDto of(Long userId, String name, BaseNutrition baseNutrition) {
return new CreateFoodDto(userId, name, baseNutrition);
public static CreateFoodDto of(Long userId, String name, BaseNutrition baseNutrition, LocalDate date) {
return new CreateFoodDto(userId, name, baseNutrition, date);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,11 @@
public class UpdateFavoriteFoodDto {

private Long favoriteFoodId;
private Long userId;
private String name;
private BaseNutrition baseNutrition;

public static UpdateFavoriteFoodDto of(Long favoriteFoodId, String name, BaseNutrition baseNutrition) {
return new UpdateFavoriteFoodDto(favoriteFoodId, name, baseNutrition);
public static UpdateFavoriteFoodDto of(Long favoriteFoodId, Long userId, String name, BaseNutrition baseNutrition) {
return new UpdateFavoriteFoodDto(favoriteFoodId, userId, name, baseNutrition);
}
}
5 changes: 3 additions & 2 deletions src/main/java/com/diareat/diareat/food/dto/UpdateFoodDto.java
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,11 @@
public class UpdateFoodDto {

private Long foodId;
private Long userId;
private String name;
private BaseNutrition baseNutrition;

public static UpdateFoodDto of(Long foodId, String name, BaseNutrition baseNutrition) {
return new UpdateFoodDto(foodId, name, baseNutrition);
public static UpdateFoodDto of(Long foodId, Long userId, String name, BaseNutrition baseNutrition) {
return new UpdateFoodDto(foodId, userId, name, baseNutrition);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,6 @@

public interface FavoriteFoodRepository extends JpaRepository<FavoriteFood, Long> {
List<FavoriteFood> findAllByUserId(Long userId);
boolean existsByIdAndUserId(Long id, Long userId); // 유저가 즐겨찾기에 추가한 음식인지 확인
boolean existsByFoodId(Long foodId); // 이미 즐겨찾기에 추가된 음식인지 확인하기 위함
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import java.util.List;

public interface FoodRepository extends JpaRepository<Food, Long> {
boolean existsByIdAndUserId(Long id, Long userId); // 유저가 먹은 음식인지 확인
List<Food> findAllByUserIdAndDate(Long userId, LocalDate date); //유저가 특정 날짜에 먹은 음식 반환
List<Food> findAllByUserIdAndDateBetween(Long userId, LocalDate startDate, LocalDate endDate); // 유저가 특정 기간 내에 먹은 음식 반환
}
37 changes: 27 additions & 10 deletions src/main/java/com/diareat/diareat/food/service/FoodService.java
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,10 @@
import com.diareat.diareat.util.exception.FoodException;
import com.diareat.diareat.util.exception.UserException;
import lombok.RequiredArgsConstructor;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.cache.annotation.Cacheable;

import java.time.DayOfWeek;
import java.time.LocalDate;
Expand All @@ -33,14 +35,16 @@ public class FoodService {
private final UserRepository userRepository;

// 촬영 후, 음식 정보 저장
@CacheEvict(value = "ResponseFoodDto", key = "#createFoodDto.getUserId()+#createFoodDto.getDate()", cacheManager = "diareatCacheManager")
@Transactional
public Long saveFood(CreateFoodDto createFoodDto) {
User user = getUserById(createFoodDto.getUserId());
Food food = Food.createFood(createFoodDto.getName(), user, createFoodDto.getBaseNutrition());
return foodRepository.save(food).getId();
}

// 회원이 특정 날짜에 먹은 음식 반환
// 회원이 특정 날짜에 먹은 음식 조회
@Cacheable(value = "ResponseFoodDto", key = "#userId+#date", cacheManager = "diareatCacheManager")
@Transactional(readOnly = true)
public List<ResponseFoodDto> getFoodListByDate(Long userId, LocalDate date){
validateUser(userId);
Expand All @@ -49,22 +53,25 @@ public List<ResponseFoodDto> getFoodListByDate(Long userId, LocalDate date){
.map(food -> ResponseFoodDto.of(food.getId(), food.getUser().getId(), food.getName(), food.getDate(), food.getTime(), food.getBaseNutrition(), food.isFavorite())).collect(Collectors.toList());
}


// 음식 정보 수정
@CacheEvict(value = "ResponseFoodDto", key = "#updateFoodDto.getUserId()", cacheManager = "diareatCacheManager")
@Transactional
public void updateFood(UpdateFoodDto updateFoodDto) {
Food food = getFoodById(updateFoodDto.getFoodId());
food.updateFood(updateFoodDto.getName(), updateFoodDto.getBaseNutrition());
foodRepository.save(food);
}

// 음식 삭제
@CacheEvict(value = "ResponseFoodDto", key = "#userId", cacheManager = "diareatCacheManager")
@Transactional
public void deleteFood(Long foodId) {
validateFood(foodId);
public void deleteFood(Long foodId, Long userId) {
validateFood(foodId, userId);
foodRepository.deleteById(foodId);
}

// 즐겨찾기에 음식 저장
@CacheEvict(value = "ResponseFavoriteFoodDto", key = "#createFavoriteFoodDto.getUserId()", cacheManager = "diareatCacheManager")
@Transactional
public Long saveFavoriteFood(CreateFavoriteFoodDto createFavoriteFoodDto) {
User user = getUserById(createFavoriteFoodDto.getUserId());
Expand All @@ -75,6 +82,7 @@ public Long saveFavoriteFood(CreateFavoriteFoodDto createFavoriteFoodDto) {
}

//즐겨찾기 음식 리스트 반환
@Cacheable(value = "ResponseFavoriteFoodDto", key = "#userId", cacheManager = "diareatCacheManager")
@Transactional(readOnly = true)
public List<ResponseFavoriteFoodDto> getFavoriteFoodList(Long userId){
validateUser(userId);
Expand All @@ -85,19 +93,23 @@ public List<ResponseFavoriteFoodDto> getFavoriteFoodList(Long userId){
}

// 즐겨찾기 음식 수정
@CacheEvict(value = "ResponseFavoriteFoodDto", key = "updateFavoriteFoodDto.getUserId()", cacheManager = "diareatCacheManager")
@Transactional
public void updateFavoriteFood(UpdateFavoriteFoodDto updateFavoriteFoodDto) {
FavoriteFood food = getFavoriteFoodById(updateFavoriteFoodDto.getFavoriteFoodId());
food.updateFavoriteFood(updateFavoriteFoodDto.getName(), updateFavoriteFoodDto.getBaseNutrition());
favoriteFoodRepository.save(food);
}

// 즐겨찾기 해제
@CacheEvict(value = "ResponseFavoriteFoodDto", key = "#userId", cacheManager = "diareatCacheManager")
@Transactional
public void deleteFavoriteFood(Long favoriteFoodId) {
validateFavoriteFood(favoriteFoodId);
public void deleteFavoriteFood(Long favoriteFoodId, Long userId) {
validateFavoriteFood(favoriteFoodId, userId);
favoriteFoodRepository.deleteById(favoriteFoodId);
}

@Cacheable(value = "ResponseNutritionSumByDateDto", key = "#userId+#date", cacheManager = "diareatCacheManager")
@Transactional(readOnly = true)
// 유저의 특정 날짜에 먹은 음식들의 영양성분별 총합 조회 (섭취영양소/기준영양소 및 비율까지 계산해서 반환, dto 구체적 협의 필요)
public ResponseNutritionSumByDateDto getNutritionSumByDate(Long userId, LocalDate date) {
Expand Down Expand Up @@ -178,6 +190,7 @@ public ResponseFoodRankDto getWorstFoodByWeek(Long userId) {
// 유저의 일기 분석 그래프 데이터 및 식습관 totalScore 조회


@Cacheable(value = "ResponseRankUserDto", key = "#userId", cacheManager = "diareatCacheManager")
@Transactional(readOnly = true)
// 유저의 식습관 점수를 기반으로 한 주간 랭킹 조회
public List<ResponseRankUserDto> getUserRankByWeek(Long userId) {
Expand Down Expand Up @@ -268,14 +281,18 @@ private void validateUser(Long userId) {
throw new UserException(ResponseCode.USER_NOT_FOUND);
}

private void validateFood(Long foodId) {
if (!foodRepository.existsById(foodId))
private void validateFood(Long foodId, Long userId) {
if(!foodRepository.existsById(foodId))
throw new FoodException(ResponseCode.FOOD_NOT_FOUND);
if (!foodRepository.existsByIdAndUserId(foodId, userId)) // 음식의 주인이 유저인지 아닌지 판정
throw new FoodException(ResponseCode.NOT_FOOD_OWNER);
}

private void validateFavoriteFood(Long favoriteFoodId) {
if (!favoriteFoodRepository.existsById(favoriteFoodId))
private void validateFavoriteFood(Long favoriteFoodId, Long userId) {
if(!favoriteFoodRepository.existsById(favoriteFoodId))
throw new FavoriteException(ResponseCode.FAVORITE_NOT_FOUND);
if(!favoriteFoodRepository.existsByIdAndUserId(favoriteFoodId, userId)) // 즐겨찾는 음식의 주인이 유저인지 아닌지 판정
throw new FavoriteException(ResponseCode.NOT_FOOD_OWNER);
}

// 1주일동안 먹은 음식들의 영양성분 총합을 요일을 Key로 한 Map을 통해 반환
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ public enum ResponseCode {

// 403 Forbidden
FORBIDDEN(HttpStatus.FORBIDDEN, false, "권한이 없습니다."),
NOT_FOOD_OWNER(HttpStatus.FORBIDDEN, false, "음식의 주인 유저가 아닙니다."),

// 404 Not Found
USER_NOT_FOUND(HttpStatus.NOT_FOUND, false, "사용자를 찾을 수 없습니다."),
Expand Down
24 changes: 13 additions & 11 deletions src/test/java/com/diareat/diareat/service/FoodServiceTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ void testSaveAndGetFood() { // 음식 정보 저장 및 해당 날짜 음식 리
User user = User.createUser("testUser", "testImage","testPassword", 1,180, 80,18, testBaseNutrition);
user.setId(1L);

CreateFoodDto createFoodDto = CreateFoodDto.of(user.getId(), "testFood", testBaseNutrition);
CreateFoodDto createFoodDto = CreateFoodDto.of(user.getId(), "testFood", testBaseNutrition, LocalDate.now());
Food food = Food.createFood("testFood", user, testBaseNutrition);
food.setId(2L);

Expand Down Expand Up @@ -89,7 +89,7 @@ void testUpdateFood() {

//when
BaseNutrition testChangedBaseNutrition = BaseNutrition.createNutrition(2,3,4,5);
foodService.updateFood(UpdateFoodDto.of(food.getId(), "testChangedFood", testChangedBaseNutrition));
foodService.updateFood(UpdateFoodDto.of(food.getId(), 1L,"testChangedFood", testChangedBaseNutrition));


assertEquals("testChangedFood", food.getName());
Expand All @@ -98,7 +98,7 @@ void testUpdateFood() {
assertEquals(4,food.getBaseNutrition().getProtein());
assertEquals(5,food.getBaseNutrition().getFat());
}
//
//
@Test
void testDeleteFood() {
//given
Expand All @@ -108,9 +108,10 @@ void testDeleteFood() {
food.setId(1L);

given(foodRepository.existsById(food.getId())).willReturn(true);
given(foodRepository.existsByIdAndUserId(food.getId(), 1L)).willReturn(true);

//when
foodService.deleteFood(food.getId());
foodService.deleteFood(food.getId(), 1L);

verify(foodRepository, times(1)).deleteById(food.getId());
}
Expand Down Expand Up @@ -152,15 +153,15 @@ void testUpdateFavoriteFood() {

//when
BaseNutrition testChangedBaseNutrition = BaseNutrition.createNutrition(2,3,4,5);
foodService.updateFavoriteFood(UpdateFavoriteFoodDto.of(favoriteFood.getId(), "testChangedFood", testChangedBaseNutrition));
foodService.updateFavoriteFood(UpdateFavoriteFoodDto.of(favoriteFood.getId(), 1L,"testChangedFood", testChangedBaseNutrition));

assertEquals("testChangedFood", favoriteFood.getName());
assertEquals(2,favoriteFood.getBaseNutrition().getKcal());
assertEquals(3,favoriteFood.getBaseNutrition().getCarbohydrate());
assertEquals(4,favoriteFood.getBaseNutrition().getProtein());
assertEquals(5,favoriteFood.getBaseNutrition().getFat());
}
//
//
@Test
void testDeleteFavoriteFood() {
//given
Expand All @@ -170,13 +171,14 @@ void testDeleteFavoriteFood() {
favoriteFood.setId(1L);

given(favoriteFoodRepository.existsById(favoriteFood.getId())).willReturn(true);
given(favoriteFoodRepository.existsByIdAndUserId(favoriteFood.getId(), 1L)).willReturn(true);

//when
foodService.deleteFavoriteFood(favoriteFood.getId());
foodService.deleteFavoriteFood(favoriteFood.getId(), 1L);

verify(favoriteFoodRepository, times(1)).deleteById(favoriteFood.getId());
}
//
//
@Test
void testNutritionSumByDate(){
//given
Expand All @@ -203,7 +205,7 @@ void testNutritionSumByDate(){
assertEquals(Math.round((((double)200 / (double)80) * 100.0)*100.0)/100.0, responseNutritionSumByDateDto.getRatioProtein());
assertEquals(Math.round((((double)250 / (double)80) * 100.0)*100.0)/100.0, responseNutritionSumByDateDto.getRatioFat());
}
//
//
@Test
void testNutritionSumByWeek(){
//given
Expand Down Expand Up @@ -261,7 +263,7 @@ void testNutritionSumByMonth(){
assertEquals(Math.round((((double)250 / (double)80) * 100.0)*100.0)/100.0, responseNutritionSumByDateDto.getRatioFat());

}
//
//
@Test
void getBest3FoodTest() {
// given
Expand All @@ -288,7 +290,7 @@ void getBest3FoodTest() {
assertEquals("Food2", top3Foods.get(1).getName());
assertEquals("Food3", top3Foods.get(2).getName());
}
//
//
@Test
void getWorst3FoodsTest() {
// given
Expand Down

0 comments on commit 5895213

Please sign in to comment.