sunkean 2 лет назад
Родитель
Сommit
21e053a79c

+ 7 - 1
src/main/java/com/izouma/nineth/repo/MetaUserGoldRepo.java

@@ -8,6 +8,7 @@ import org.springframework.data.jpa.repository.Query;
 
 import javax.transaction.Transactional;
 import java.util.List;
+import java.util.Optional;
 import java.util.Set;
 
 public interface MetaUserGoldRepo extends JpaRepository<MetaUserGold, Long>, JpaSpecificationExecutor<MetaUserGold> {
@@ -16,7 +17,12 @@ public interface MetaUserGoldRepo extends JpaRepository<MetaUserGold, Long>, Jpa
     @Transactional
     void softDelete(Long id);
 
-    MetaUserGold findByUserIdAndDel(Long userId, boolean del);
+    Optional<MetaUserGold> findByUserIdAndDel(Long userId, boolean del);
 
     List<MetaUserGold> findAllByUserIdInAndDel(Set<Long> userIds, boolean del);
+
+    @Query("update MetaUserGold m set m.num = ?2 where m.userId = ?1")
+    @Modifying
+    @Transactional
+    void updateNumByUserId(Long userId, int num);
 }

+ 32 - 19
src/main/java/com/izouma/nineth/service/MetaUserGoldService.java

@@ -1,5 +1,6 @@
 package com.izouma.nineth.service;
 
+import com.izouma.nineth.annotations.RedisLock;
 import com.izouma.nineth.domain.MetaUserGold;
 import com.izouma.nineth.domain.MetaUserGoldRecord;
 import com.izouma.nineth.dto.MetaRestResult;
@@ -17,6 +18,7 @@ import org.springframework.stereotype.Service;
 
 import javax.transaction.Transactional;
 import java.util.*;
+import java.util.stream.Collectors;
 
 @Service
 @AllArgsConstructor
@@ -35,13 +37,13 @@ public class MetaUserGoldService {
 
     @Transactional
     public void initMetaUserGold(String userIds) {
-        String[] split = userIds.split(" ");
-        List<MetaUserGold> metaUserGolds = new ArrayList<>();
-        List<MetaUserGoldRecord> metaUserGoldRecords = new ArrayList<>();
-        Arrays.stream(split).forEach(userId -> {
-            metaUserGolds.add(new MetaUserGold(Long.parseLong(userId), 0));
-            metaUserGoldRecords.add(new MetaUserGoldRecord(Long.parseLong(userId), 0, 0, 0, "初始化"));
-        });
+        List<MetaUserGold> metaUserGolds = Arrays.stream(userIds.split(" "))
+                                                 .map(Long::parseLong)
+                                                 .map(userId -> new MetaUserGold(userId, 0))
+                                                 .collect(Collectors.toList());
+        List<MetaUserGoldRecord> metaUserGoldRecords = metaUserGolds.stream()
+                                                                    .map(metaUserGold -> new MetaUserGoldRecord(metaUserGold.getUserId(), 0, 0, 0, "初始化"))
+                                                                    .collect(Collectors.toList());
         metaUserGoldRepo.saveAll(metaUserGolds);
         metaUserGoldRecordRepo.saveAll(metaUserGoldRecords);
     }
@@ -75,26 +77,37 @@ public class MetaUserGoldService {
      * @return result
      */
     @Transactional
+    @RedisLock("'userGoldLock::'+#userId")
     public MetaRestResult<MetaUserGold> changeNum(Long userId, int num, String remark) {
-        MetaUserGold metaUserGold = metaUserGoldRepo.findByUserIdAndDel(userId, false);
-        if (Objects.isNull(metaUserGold)) {
-            log.info(String.format("不存在用户[%S]记录。默认初始化", userId));
-            initMetaUserGold(String.valueOf(userId));
-            metaUserGold = metaUserGoldRepo.findByUserIdAndDel(userId, false);
+        Objects.requireNonNull(userId, "用户ID不能为空");
+        Objects.requireNonNull(remark, "备注不能为空");
+        MetaUserGold metaUserGold = metaUserGoldRepo.findByUserIdAndDel(userId, false)
+                                                    .orElseGet(() -> {
+                                                        log.info(String.format("不存在用户[%S]记录。默认初始化", userId));
+                                                        initMetaUserGold(String.valueOf(userId));
+                                                        return metaUserGoldRepo.findByUserIdAndDel(userId, false).orElse(null);
+                                                    });
+        if (metaUserGold == null) {
+            throw new RuntimeException(String.format("无法初始化用户[%S]记录", userId));
         }
-        // 操作前金币数量
         int nowNum = metaUserGold.getNum();
+        int afterNum;
+        try {
+            afterNum = Math.addExact(nowNum, num);
+        } catch (Exception e) {
+            throw new RuntimeException(String.format("金额操作发生异常[%S]", e.getMessage()));
+        }
+        if (afterNum < 0) {
+            throw new RuntimeException(String.format("用户[%S] 当前金币剩余[%S],无法进行数量为[%S]的操作", userId, nowNum, -num));
+        }
         MetaUserGoldRecord metaUserGoldRecord = new MetaUserGoldRecord();
         metaUserGoldRecord.setUserId(userId);
         metaUserGoldRecord.setBeforeNum(nowNum);
-        metaUserGoldRecord.setAfterNum(nowNum + num);
+        metaUserGoldRecord.setAfterNum(afterNum);
         metaUserGoldRecord.setOperationNum(num);
         metaUserGoldRecord.setRemark(remark);
-        if (metaUserGoldRecord.getAfterNum() < 0) {
-            return MetaRestResult.returnError(String.format("用户[%S] 当前金币剩余[%S] 本次操作需要金币数量为[%S]", userId, nowNum, -num));
-        }
-        metaUserGold.setNum(nowNum + num);
         metaUserGoldRecordRepo.save(metaUserGoldRecord);
-        return MetaRestResult.returnSuccess(metaUserGoldRepo.save(metaUserGold));
+        metaUserGoldRepo.updateNumByUserId(userId, afterNum);
+        return MetaRestResult.returnSuccess(metaUserGold);
     }
 }

+ 7 - 3
src/main/java/com/izouma/nineth/web/MetaUserGoldController.java

@@ -70,10 +70,14 @@ public class MetaUserGoldController extends BaseController {
 
     @GetMapping("/{userId}/queryNum")
     public MetaRestResult<Integer> queryGoldNum(@PathVariable Long userId) {
-        MetaUserGold metaUserGold = metaUserGoldRepo.findByUserIdAndDel(userId, false);
-        if (Objects.isNull(metaUserGold)) {
+        MetaUserGold metaUserGold = metaUserGoldRepo.findByUserIdAndDel(userId, false).orElseGet(() -> {
             metaUserGoldService.initMetaUserGold(String.valueOf(userId));
-            return MetaRestResult.returnSuccess(0);
+            return metaUserGoldRepo.findByUserIdAndDel(userId, false).orElse(null);
+        });
+        if (Objects.isNull(metaUserGold)) {
+            String errMMsg = String.format("当前用户[%S]金币账户数据不存在且无法初始化数据", userId);
+            log.error(errMMsg);
+            return MetaRestResult.returnError(errMMsg);
         }
         return MetaRestResult.returnSuccess(metaUserGold.getNum());
     }