@@ -39,6 +39,7 @@ public class MemberServiceImpl implements MemberService {
3939 private int gracePeriodDays ;
4040
4141 @ Override
42+ @ Transactional (readOnly = true )
4243 public Member findMemberByEmail (String email ) {
4344 return memberRepository .findByEmail (email ).orElseThrow (()-> new BusinessException (ErrorCode .EMAIL_NOT_FOUND ));
4445 }
@@ -52,18 +53,35 @@ public Member findById(Long id) {
5253 @ Override
5354 @ CacheEvict (cacheNames = com .divary .global .config .CacheConfig .CACHE_MEMBER_BY_ID , key = "#member.id" , condition = "#member.id != null" )
5455 public Member saveMember (Member member ) {
56+ // If member has an ID, it might be a detached entity from cache
57+ // Re-fetch from DB to get managed entity with proper version
58+ if (member .getId () != null ) {
59+ Member managedMember = memberRepository .findById (member .getId ())
60+ .orElseThrow (() -> new BusinessException (ErrorCode .MEMBER_NOT_FOUND ));
61+
62+ // Copy all fields from detached member to managed member
63+ managedMember .setEmail (member .getEmail ());
64+ managedMember .setLevel (member .getLevel ());
65+ managedMember .setRole (member .getRole ());
66+ managedMember .setStatus (member .getStatus ());
67+ managedMember .setDeactivatedAt (member .getDeactivatedAt ());
68+
69+ return managedMember ; // JPA dirty checking will save this
70+ }
71+
72+ // New entity - just save directly
5573 return memberRepository .save (member );
5674 }
5775
5876
5977
60- @ CacheEvict (cacheNames = com .divary .global .config .CacheConfig .CACHE_MEMBER_BY_ID , key = "#userId" )
78+ @ CacheEvict (cacheNames = com .divary .global .config .CacheConfig .CACHE_MEMBER_BY_ID , key = "#userId" , beforeInvocation = false )
6179 public void updateLevel (Long userId , MyPageLevelRequestDTO requestDTO ) {
6280 Levels level = EnumValidator .validateEnum (Levels .class , requestDTO .getLevel ().name ());
6381
64-
6582 Member member = memberRepository .findById (userId ).orElseThrow (()-> new BusinessException (ErrorCode .MEMBER_NOT_FOUND ));
6683 member .setLevel (level );
84+ // Cache evicted after successful update
6785 }
6886
6987 @ Override
@@ -83,7 +101,7 @@ public MyPageImageResponseDTO uploadLicense(MultipartFile image, Long userId) {
83101
84102 @ Override
85103 @ Transactional
86- @ CacheEvict (cacheNames = com .divary .global .config .CacheConfig .CACHE_MEMBER_BY_ID , key = "#memberId" )
104+ @ CacheEvict (cacheNames = com .divary .global .config .CacheConfig .CACHE_MEMBER_BY_ID , key = "#memberId" , beforeInvocation = false )
87105 public DeactivateResponse requestToDeleteMember (Long memberId ) {
88106 Member member = memberRepository .findById (memberId ).orElseThrow (()-> new BusinessException (ErrorCode .MEMBER_NOT_FOUND ));
89107
@@ -96,18 +114,20 @@ public DeactivateResponse requestToDeleteMember(Long memberId) {
96114 .plusDays (gracePeriodDays );
97115
98116 return new DeactivateResponse (scheduledDeletionAt );
117+ // Cache evicted after successful update
99118 }
100119
101120 @ Override
102121 @ Transactional
103- @ CacheEvict (cacheNames = com .divary .global .config .CacheConfig .CACHE_MEMBER_BY_ID , key = "#memberId" )
122+ @ CacheEvict (cacheNames = com .divary .global .config .CacheConfig .CACHE_MEMBER_BY_ID , key = "#memberId" , beforeInvocation = false )
104123 public void cancelDeleteMember (Long memberId ) {
105124 Member member = memberRepository .findById (memberId ).orElseThrow (() -> new BusinessException (ErrorCode .MEMBER_NOT_FOUND ));
106125
107126 // DEACTIVATED 상태일 때만 취소 가능
108127 if (member .getStatus () == Status .DEACTIVATED ) {
109128 member .cancelDeletion ();
110129 }
130+ // Cache evicted after successful update
111131 }
112132 @ Override
113133 @ Transactional
0 commit comments