diff --git a/backend/src/main/java/net/pengcook/authentication/service/LoginService.java b/backend/src/main/java/net/pengcook/authentication/service/LoginService.java index 59e89d75..a6f0b238 100644 --- a/backend/src/main/java/net/pengcook/authentication/service/LoginService.java +++ b/backend/src/main/java/net/pengcook/authentication/service/LoginService.java @@ -19,6 +19,7 @@ import net.pengcook.user.domain.User; import net.pengcook.user.repository.UserRepository; import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; @Service @RequiredArgsConstructor @@ -29,6 +30,7 @@ public class LoginService { private final JwtTokenManager jwtTokenManager; private final S3ClientService s3ClientService; + @Transactional(readOnly = true) public GoogleLoginResponse loginWithGoogle(GoogleLoginRequest googleLoginRequest) { FirebaseToken decodedToken = decodeIdToken(googleLoginRequest.idToken()); String email = decodedToken.getEmail(); @@ -46,6 +48,7 @@ public GoogleLoginResponse loginWithGoogle(GoogleLoginRequest googleLoginRequest return new GoogleLoginResponse(true, accessToken, refreshToken); } + @Transactional public GoogleSignUpResponse signUpWithGoogle(GoogleSignUpRequest googleSignUpRequest) { User user = createUser(googleSignUpRequest); @@ -73,6 +76,12 @@ public TokenRefreshResponse refresh(String refreshToken) { ); } + @Transactional(readOnly = true) + public void checkToken(long userId) { + userRepository.findById(userId) + .orElseThrow(() -> new NoSuchUserException("존재하지 않는 사용자입니다.")); + } + private User createUser(GoogleSignUpRequest googleSignUpRequest) { FirebaseToken decodedToken = decodeIdToken(googleSignUpRequest.idToken()); @@ -100,9 +109,4 @@ private FirebaseToken decodeIdToken(String idToken) { throw new FirebaseTokenException("구글 인증에 실패했습니다."); } } - - public void checkToken(long userId) { - userRepository.findById(userId) - .orElseThrow(() -> new NoSuchUserException("존재하지 않는 사용자입니다.")); - } } diff --git a/backend/src/main/java/net/pengcook/category/service/CategoryService.java b/backend/src/main/java/net/pengcook/category/service/CategoryService.java index 729cfb2a..0364f488 100644 --- a/backend/src/main/java/net/pengcook/category/service/CategoryService.java +++ b/backend/src/main/java/net/pengcook/category/service/CategoryService.java @@ -8,6 +8,7 @@ import net.pengcook.category.repository.CategoryRepository; import net.pengcook.recipe.domain.Recipe; import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; @Service @RequiredArgsConstructor @@ -16,10 +17,12 @@ public class CategoryService { private final CategoryRepository categoryRepository; private final CategoryRecipeRepository categoryRecipeRepository; + @Transactional public void saveCategories(Recipe recipe, List categories) { categories.forEach(category -> saveCategoryRecipe(recipe, category)); } + @Transactional public void deleteCategoryRecipe(Recipe recipe) { categoryRecipeRepository.deleteByRecipe(recipe); } diff --git a/backend/src/main/java/net/pengcook/comment/service/CommentService.java b/backend/src/main/java/net/pengcook/comment/service/CommentService.java index d140873c..dc4275b4 100644 --- a/backend/src/main/java/net/pengcook/comment/service/CommentService.java +++ b/backend/src/main/java/net/pengcook/comment/service/CommentService.java @@ -1,6 +1,5 @@ package net.pengcook.comment.service; -import jakarta.transaction.Transactional; import java.time.LocalDateTime; import java.util.List; import lombok.RequiredArgsConstructor; @@ -16,6 +15,7 @@ import net.pengcook.user.domain.User; import net.pengcook.user.repository.UserRepository; import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; @Service @RequiredArgsConstructor @@ -25,6 +25,7 @@ public class CommentService { private final RecipeRepository recipeRepository; private final UserRepository userRepository; + @Transactional(readOnly = true) public List readComments(Long recipeId, UserInfo userInfo) { List comments = commentRepository.findByRecipeId(recipeId); @@ -61,10 +62,12 @@ public void deleteComment(long commentId, UserInfo userInfo) { recipe.decreaseCommentCount(); } + @Transactional public void deleteCommentsByRecipe(long recipeId) { commentRepository.deleteByRecipeId(recipeId); } + @Transactional public void deleteCommentsByUser(long userId) { commentRepository.deleteByUserId(userId); } diff --git a/backend/src/main/java/net/pengcook/ingredient/service/IngredientRecipeService.java b/backend/src/main/java/net/pengcook/ingredient/service/IngredientRecipeService.java index 46e1b488..3512a6ac 100644 --- a/backend/src/main/java/net/pengcook/ingredient/service/IngredientRecipeService.java +++ b/backend/src/main/java/net/pengcook/ingredient/service/IngredientRecipeService.java @@ -8,6 +8,7 @@ import net.pengcook.ingredient.repository.IngredientRecipeRepository; import net.pengcook.recipe.domain.Recipe; import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; @Service @RequiredArgsConstructor @@ -16,11 +17,13 @@ public class IngredientRecipeService { private final IngredientRecipeRepository ingredientRecipeRepository; private final IngredientSubstitutionService ingredientSubstitutionService; + @Transactional public IngredientRecipe save(Ingredient ingredient, Recipe recipe, Requirement requirement) { IngredientRecipe ingredientRecipe = new IngredientRecipe(ingredient, recipe, requirement); return ingredientRecipeRepository.save(ingredientRecipe); } + @Transactional public void deleteIngredientRecipe(long recipeId) { List ingredientRecipes = ingredientRecipeRepository.findAllByRecipeId(recipeId); for (IngredientRecipe ingredientRecipe : ingredientRecipes) { diff --git a/backend/src/main/java/net/pengcook/ingredient/service/IngredientService.java b/backend/src/main/java/net/pengcook/ingredient/service/IngredientService.java index 53e0a66c..63918ed1 100644 --- a/backend/src/main/java/net/pengcook/ingredient/service/IngredientService.java +++ b/backend/src/main/java/net/pengcook/ingredient/service/IngredientService.java @@ -1,7 +1,6 @@ package net.pengcook.ingredient.service; -import jakarta.transaction.Transactional; import java.util.HashSet; import java.util.List; import lombok.Getter; @@ -14,9 +13,9 @@ import net.pengcook.ingredient.repository.IngredientRepository; import net.pengcook.recipe.domain.Recipe; import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; @Service -@Transactional @RequiredArgsConstructor @Getter public class IngredientService { @@ -25,6 +24,7 @@ public class IngredientService { private final IngredientRecipeService ingredientRecipeService; private final IngredientSubstitutionService ingredientSubstitutionService; + @Transactional public void register(List requests, Recipe recipe) { validateDuplicateNames(getIngredientNames(requests)); for (IngredientCreateRequest request : requests) { diff --git a/backend/src/main/java/net/pengcook/ingredient/service/IngredientSubstitutionService.java b/backend/src/main/java/net/pengcook/ingredient/service/IngredientSubstitutionService.java index 4217fe77..501a883b 100644 --- a/backend/src/main/java/net/pengcook/ingredient/service/IngredientSubstitutionService.java +++ b/backend/src/main/java/net/pengcook/ingredient/service/IngredientSubstitutionService.java @@ -8,6 +8,7 @@ import net.pengcook.ingredient.domain.Requirement; import net.pengcook.ingredient.repository.IngredientSubstitutionRepository; import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; @Service @RequiredArgsConstructor @@ -15,11 +16,13 @@ public class IngredientSubstitutionService { private final IngredientSubstitutionRepository ingredientSubstitutionRepository; + @Transactional public void save(IngredientRecipe ingredientRecipe, Ingredient substitution) { IngredientSubstitution ingredientSubstitution = new IngredientSubstitution(ingredientRecipe, substitution); ingredientSubstitutionRepository.save(ingredientSubstitution); } + @Transactional public void delete(IngredientRecipe ingredientRecipe) { if (ingredientRecipe.getRequirement() == Requirement.ALTERNATIVE) { List substitutions = diff --git a/backend/src/main/java/net/pengcook/like/service/RecipeLikeService.java b/backend/src/main/java/net/pengcook/like/service/RecipeLikeService.java index 54875022..711ab76e 100644 --- a/backend/src/main/java/net/pengcook/like/service/RecipeLikeService.java +++ b/backend/src/main/java/net/pengcook/like/service/RecipeLikeService.java @@ -1,6 +1,5 @@ package net.pengcook.like.service; -import jakarta.transaction.Transactional; import lombok.RequiredArgsConstructor; import net.pengcook.authentication.domain.UserInfo; import net.pengcook.like.domain.RecipeLike; @@ -13,6 +12,7 @@ import net.pengcook.user.domain.User; import net.pengcook.user.repository.UserRepository; import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; @Service @RequiredArgsConstructor @@ -22,6 +22,7 @@ public class RecipeLikeService { private final UserRepository userRepository; private final RecipeRepository recipeRepository; + @Transactional(readOnly = true) public RecipeLikeResponse readLike(UserInfo userInfo, long recipeId) { boolean isLike = likeRepository.existsByUserIdAndRecipeId(userInfo.getId(), recipeId); @@ -60,10 +61,12 @@ public void deleteLike(UserInfo userInfo, long recipeId) { recipeRepository.save(recipe); } + @Transactional public void deleteLikesByRecipe(long recipeId) { likeRepository.deleteByRecipeId(recipeId); } + @Transactional public void deleteLikesByUser(long userId) { likeRepository.deleteByUserId(userId); } diff --git a/backend/src/main/java/net/pengcook/recipe/service/RecipeService.java b/backend/src/main/java/net/pengcook/recipe/service/RecipeService.java index bb3778bb..8da1eac5 100644 --- a/backend/src/main/java/net/pengcook/recipe/service/RecipeService.java +++ b/backend/src/main/java/net/pengcook/recipe/service/RecipeService.java @@ -33,7 +33,6 @@ import org.springframework.transaction.annotation.Transactional; @Service -@Transactional @RequiredArgsConstructor public class RecipeService { @@ -49,6 +48,7 @@ public class RecipeService { private final CommentService commentService; private final RecipeLikeService recipeLikeService; + @Transactional(readOnly = true) public List readRecipes(UserInfo userInfo, PageRecipeRequest pageRecipeRequest) { Pageable pageable = pageRecipeRequest.getPageable(); List recipeIds = recipeRepository.findRecipeIdsByCategoryAndKeyword( @@ -66,6 +66,7 @@ public List readRecipes(UserInfo userInfo, PageRecip .toList(); } + @Transactional(readOnly = true) public List readLikeRecipes(UserInfo userInfo) { List likeRecipeIds = likeRepository.findRecipeIdsByUserId(userInfo.getId()); List recipeHomeResponses = recipeRepository.findRecipeData(likeRecipeIds); @@ -76,6 +77,7 @@ public List readLikeRecipes(UserInfo userInfo) { .toList(); } + @Transactional public RecipeResponse createRecipe(UserInfo userInfo, RecipeRequest recipeRequest) { User author = userRepository.findById(userInfo.getId()).orElseThrow(); String thumbnailUrl = s3ClientService.getImageUrl(recipeRequest.thumbnail()).url(); @@ -96,6 +98,7 @@ public RecipeResponse createRecipe(UserInfo userInfo, RecipeRequest recipeReques return new RecipeResponse(savedRecipe); } + @Transactional(readOnly = true) public RecipeDescriptionResponse readRecipeDescription(UserInfo userInfo, long recipeId) { List recipeDataResponses = recipeRepository.findRecipeData(recipeId); @@ -107,6 +110,7 @@ public RecipeDescriptionResponse readRecipeDescription(UserInfo userInfo, long r ); } + @Transactional public void deleteRecipe(UserInfo userInfo, long recipeId) { Optional targetRecipe = recipeRepository.findById(recipeId); diff --git a/backend/src/main/java/net/pengcook/recipe/service/RecipeStepService.java b/backend/src/main/java/net/pengcook/recipe/service/RecipeStepService.java index 80d85f36..6eb51a71 100644 --- a/backend/src/main/java/net/pengcook/recipe/service/RecipeStepService.java +++ b/backend/src/main/java/net/pengcook/recipe/service/RecipeStepService.java @@ -18,7 +18,6 @@ import org.springframework.transaction.annotation.Transactional; @Service -@Transactional @RequiredArgsConstructor public class RecipeStepService { @@ -26,17 +25,20 @@ public class RecipeStepService { private final RecipeRepository recipeRepository; private final S3ClientService s3ClientService; + @Transactional(readOnly = true) public List readRecipeSteps(long recipeId) { List recipeSteps = recipeStepRepository.findAllByRecipeIdOrderBySequence(recipeId); return convertToRecipeStepResponses(recipeSteps); } + @Transactional public void saveRecipeSteps(Long savedRecipeId, List recipeStepRequests) { Recipe savedRecipe = recipeRepository.findById(savedRecipeId) .orElseThrow(() -> new NotFoundException("해당되는 레시피가 없습니다.")); recipeStepRequests.forEach(recipeStepRequest -> saveRecipeStep(savedRecipe, recipeStepRequest)); } + @Transactional public void deleteRecipeStepsByRecipe(long recipeId) { recipeStepRepository.deleteByRecipeId(recipeId); } diff --git a/backend/src/main/java/net/pengcook/user/service/UserService.java b/backend/src/main/java/net/pengcook/user/service/UserService.java index 9c70d645..9a063b03 100644 --- a/backend/src/main/java/net/pengcook/user/service/UserService.java +++ b/backend/src/main/java/net/pengcook/user/service/UserService.java @@ -1,6 +1,5 @@ package net.pengcook.user.service; -import jakarta.transaction.Transactional; import java.util.List; import java.util.stream.Collectors; import lombok.AllArgsConstructor; @@ -28,6 +27,7 @@ import net.pengcook.user.repository.UserReportRepository; import net.pengcook.user.repository.UserRepository; import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; @Service @AllArgsConstructor @@ -43,6 +43,7 @@ public class UserService { private final UserReportRepository userReportRepository; private final S3ClientService s3ClientService; + @Transactional(readOnly = true) public ProfileResponse getUserById(long userId) { User user = userRepository.findById(userId) .orElseThrow(() -> new UserNotFoundException("사용자를 찾을 수 없습니다.")); @@ -50,6 +51,7 @@ public ProfileResponse getUserById(long userId) { return new ProfileResponse(user, recipeCount); } + @Transactional(readOnly = true) public UsernameCheckResponse checkUsername(String username) { boolean userExists = userRepository.existsByUsername(username); return new UsernameCheckResponse(!userExists); @@ -74,6 +76,7 @@ public UpdateProfileResponse updateProfile(long userId, UpdateProfileRequest upd return new UpdateProfileResponse(user); } + @Transactional public UserBlockResponse blockUser(long blockerId, long blockeeId) { User blocker = userRepository.findById(blockerId) .orElseThrow(() -> new UserNotFoundException("정상적으로 로그인되지 않았습니다.")); @@ -86,6 +89,7 @@ public UserBlockResponse blockUser(long blockerId, long blockeeId) { new UserResponse(userBlock.getBlockee())); } + @Transactional public ReportResponse report(long reporterId, ReportRequest reportRequest) { User reporter = userRepository.findById(reporterId) .orElseThrow(() -> new NotFoundException("신고자 정보를 조회할 수 없습니다.")); @@ -104,6 +108,7 @@ public ReportResponse report(long reporterId, ReportRequest reportRequest) { return new ReportResponse(savedUserReport); } + @Transactional(readOnly = true) public BlockedUserGroup getBlockedUserGroup(long blockerId) { return userBlockRepository.findAllByBlockerId(blockerId).stream()