@@ -111,47 +111,54 @@ public PollVoteDto vote(Long pollId, Long pollItemsId, Long memberId) {
111111 if (!(member .getRole ().name ().equals ("USER" ) || member .getRole ().name ().equals ("ADMIN" ))) {
112112 throw new ResponseStatusException (HttpStatus .FORBIDDEN , "투표 권한이 없습니다." );
113113 }
114- // 기존 투표 내역 조회
115- var existingVoteOpt = pollVoteRepository .findByMemberIdAndPoll_PollId (memberId , pollId );
116- if (existingVoteOpt .isPresent ()) {
117- PollVote existingVote = existingVoteOpt .get ();
118- if (existingVote .getPollOptions ().getPollItemsId ().equals (pollItemsId )) {
119- throw new ResponseStatusException (HttpStatus .BAD_REQUEST , "이미 투표하셨습니다." );
120- } else {
121- pollVoteRepository .deleteByMemberIdAndPoll_PollId (memberId , pollId );
122- PollVote pollVote = PollVote .builder ()
123- .poll (poll )
124- .pollOptions (pollOptions )
125- .memberId (memberId )
126- .build ();
127- PollVote savedVote = pollVoteRepository .save (pollVote );
128- Long voteCount = pollVoteRepository .countByPollOptionId (pollItemsId );
129- return PollVoteDto .builder ()
130- .pollVoteId (savedVote .getPollVoteId ())
131- .pollId (pollId )
132- .pollItemsId (pollItemsId )
133- .memberId (memberId )
134- .voteCount (voteCount )
135- .message ("투표 항목을 변경하였습니다." )
136- .build ();
114+
115+ try {
116+ // 기존 투표 내역 조회
117+ var existingVoteOpt = pollVoteRepository .findByMemberIdAndPoll_PollId (memberId , pollId );
118+ if (existingVoteOpt .isPresent ()) {
119+ PollVote existingVote = existingVoteOpt .get ();
120+ if (existingVote .getPollOptions ().getPollItemsId ().equals (pollItemsId )) {
121+ throw new ResponseStatusException (HttpStatus .BAD_REQUEST , "이미 투표하셨습니다." );
122+ } else {
123+ pollVoteRepository .deleteByMemberIdAndPoll_PollId (memberId , pollId );
124+ PollVote pollVote = PollVote .builder ()
125+ .poll (poll )
126+ .pollOptions (pollOptions )
127+ .memberId (memberId )
128+ .build ();
129+ PollVote savedVote = pollVoteRepository .save (pollVote );
130+ Long voteCount = pollVoteRepository .countByPollOptionId (pollItemsId );
131+ return PollVoteDto .builder ()
132+ .pollVoteId (savedVote .getPollVoteId ())
133+ .pollId (pollId )
134+ .pollItemsId (pollItemsId )
135+ .memberId (memberId )
136+ .voteCount (voteCount )
137+ .message ("투표 항목을 변경하였습니다." )
138+ .build ();
139+ }
137140 }
141+ // 기존 투표 내역이 없으면 정상 투표
142+ PollVote pollVote = PollVote .builder ()
143+ .poll (poll )
144+ .pollOptions (pollOptions )
145+ .memberId (memberId )
146+ .build ();
147+ PollVote savedVote = pollVoteRepository .save (pollVote );
148+ Long voteCount = pollVoteRepository .countByPollOptionId (pollItemsId );
149+ return PollVoteDto .builder ()
150+ .pollVoteId (savedVote .getPollVoteId ())
151+ .pollId (pollId )
152+ .pollItemsId (pollItemsId )
153+ .memberId (memberId )
154+ .voteCount (voteCount )
155+ .message ("투표가 완료되었습니다." )
156+ .build ();
157+ } catch (org .springframework .dao .DataIntegrityViolationException e ) {
158+ // 동시성 문제로 인한 중복 투표 시도 (unique constraint violation)
159+ log .warn ("중복 투표 시도 감지 - memberId: {}, pollId: {}" , memberId , pollId , e );
160+ throw new ResponseStatusException (HttpStatus .BAD_REQUEST , "이미 투표하셨습니다. 중복 투표는 불가능합니다." );
138161 }
139- // 기존 투표 내역이 없으면 정상 투표
140- PollVote pollVote = PollVote .builder ()
141- .poll (poll )
142- .pollOptions (pollOptions )
143- .memberId (memberId )
144- .build ();
145- PollVote savedVote = pollVoteRepository .save (pollVote );
146- Long voteCount = pollVoteRepository .countByPollOptionId (pollItemsId );
147- return PollVoteDto .builder ()
148- .pollVoteId (savedVote .getPollVoteId ())
149- .pollId (pollId )
150- .pollItemsId (pollItemsId )
151- .memberId (memberId )
152- .voteCount (voteCount )
153- .message ("투표가 완료되었습니다." )
154- .build ();
155162 }
156163
157164 @ Override
0 commit comments