Parcourir la source

1.修改WalletService,提交后释放锁

qmj il y a 1 semaine
Parent
commit
d54e551461
1 fichiers modifiés avec 154 ajouts et 69 suppressions
  1. 154 69
      ruoyi-admin/src/main/java/com/ruoyi/app/service/WalletService.java

+ 154 - 69
ruoyi-admin/src/main/java/com/ruoyi/app/service/WalletService.java

@@ -20,6 +20,8 @@ import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Component;
 import org.springframework.transaction.annotation.Propagation;
 import org.springframework.transaction.annotation.Transactional;
+import org.springframework.transaction.support.TransactionSynchronization;
+import org.springframework.transaction.support.TransactionSynchronizationManager;
 
 import java.math.BigDecimal;
 import java.util.Date;
@@ -65,8 +67,8 @@ public class WalletService {
             throw new ServiceException(MessageUtils.message("no.wallet.common.cs.error"));
         }
 
-        InfoUser user=userService.getById(userId);
-        if(user==null){
+        InfoUser user = userService.getById(userId);
+        if (user == null) {
             throw new ServiceException(MessageUtils.message("no.wallet.noexist.userinfo"));
         }
         String lockKey = "wallet:lock:" + userId;
@@ -75,6 +77,7 @@ public class WalletService {
         try {
             // 尝试获取锁
             if (lock.tryLock(LOCK_WAIT_TIME, LOCK_TIMEOUT, TimeUnit.SECONDS)) {
+                boolean releaseInFinally = true;
                 try {
                     // 2. 获取用户钱包
                     LambdaQueryWrapper<UserWallet> walletQuery = new LambdaQueryWrapper<>();
@@ -110,8 +113,19 @@ public class WalletService {
                     if (!updateSuccess) {
                         throw new ServiceException(MessageUtils.message("no.wallet.update.faile"));
                     }
+                    releaseInFinally = false;
+                    TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronization() {
+                        @Override
+                        public void afterCommit() {
+                            if (lock.isHeldByCurrentThread()) {
+                                lock.unlock();
+                            }
+                        }
+                    });
                 } finally {
-                    lock.unlock();
+                    if (releaseInFinally && lock.isHeldByCurrentThread()) {
+                        lock.unlock();
+                    }
                 }
             } else {
                 throw new ServiceException(MessageUtils.message("no.system.busy.try.again"));
@@ -135,8 +149,8 @@ public class WalletService {
         if (userId == null || ddId == null || points == null || points <= 0) {
             throw new ServiceException(MessageUtils.message("no.wallet.common.cs.error"));
         }
-        InfoUser user=userService.getById(userId);
-        if(user==null){
+        InfoUser user = userService.getById(userId);
+        if (user == null) {
             throw new ServiceException(MessageUtils.message("no.wallet.noexist.userinfo"));
         }
 
@@ -146,6 +160,7 @@ public class WalletService {
         try {
             // 尝试获取锁
             if (lock.tryLock(LOCK_WAIT_TIME, LOCK_TIMEOUT, TimeUnit.SECONDS)) {
+                boolean releaseInFinally = true;
                 try {
                     // 2. 获取用户钱包
                     LambdaQueryWrapper<UserWallet> walletQuery = new LambdaQueryWrapper<>();
@@ -186,8 +201,19 @@ public class WalletService {
                     if (!updateSuccess) {
                         throw new ServiceException(MessageUtils.message("no.wallet.update.faile"));
                     }
+                    releaseInFinally = false;
+                    TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronization() {
+                        @Override
+                        public void afterCommit() {
+                            if (lock.isHeldByCurrentThread()) {
+                                lock.unlock();
+                            }
+                        }
+                    });
                 } finally {
-                    lock.unlock();
+                    if (releaseInFinally && lock.isHeldByCurrentThread()) {
+                        lock.unlock();
+                    }
                 }
             } else {
                 throw new ServiceException(MessageUtils.message("no.system.busy.try.again"));
@@ -201,17 +227,17 @@ public class WalletService {
     /**
      * 增加余额
      *
-     * @param userId  用户ID
-     * @param amount  增加金额
+     * @param userId 用户ID
+     * @param amount 增加金额
      */
     @Transactional(rollbackFor = Exception.class)
-    public void addBalance(Long userId, BigDecimal amount,UserBilling billing) {
+    public void addBalance(Long userId, BigDecimal amount, UserBilling billing) {
         // 1. 参数校验
         if (userId == null || amount == null || amount.compareTo(BigDecimal.ZERO) <= 0) {
             throw new ServiceException(MessageUtils.message("no.wallet.common.cs.error"));
         }
-        InfoUser user=userService.getById(userId);
-        if(user==null){
+        InfoUser user = userService.getById(userId);
+        if (user == null) {
             throw new ServiceException(MessageUtils.message("no.wallet.noexist.userinfo"));
         }
         String lockKey = ConstantUtil.WalletBalanceLock + userId;
@@ -220,6 +246,7 @@ public class WalletService {
         try {
             // 尝试获取锁
             if (lock.tryLock(LOCK_WAIT_TIME, LOCK_TIMEOUT, TimeUnit.SECONDS)) {
+                boolean releaseInFinally = true;
                 try {
                     // 2. 获取用户钱包
                     LambdaQueryWrapper<UserWallet> walletQuery = new LambdaQueryWrapper<>();
@@ -228,17 +255,17 @@ public class WalletService {
                     if (userWallet == null) {
                         throw new ServiceException(MessageUtils.message("no.user.wallet.not.exist"));
                     }
-                    Double behalfAmount=billing.getBehalfAmount();
+                    Double behalfAmount = billing.getBehalfAmount();
                     // 3. 更新余额
                     BigDecimal newBalance = userWallet.getBalanceWallet().add(amount);
-                    if(behalfAmount!=null){
-                        newBalance=newBalance.subtract(BigDecimal.valueOf(behalfAmount));
+                    if (behalfAmount != null) {
+                        newBalance = newBalance.subtract(BigDecimal.valueOf(behalfAmount));
                         //该订单存在冻结金额,解冻金额
-                        long blockedCount=billingService.count(new LambdaQueryWrapper<UserBilling>().eq(UserBilling::getUserId, userId).eq(UserBilling::getDdId,billing.getDdId()).eq(UserBilling::getType,"4"));
-                        if(blockedCount>0){
-                            BigDecimal newBlocked= userWallet.getBlockedFunds().subtract(BigDecimal.valueOf(behalfAmount));
+                        long blockedCount = billingService.count(new LambdaQueryWrapper<UserBilling>().eq(UserBilling::getUserId, userId).eq(UserBilling::getDdId, billing.getDdId()).eq(UserBilling::getType, "4"));
+                        if (blockedCount > 0) {
+                            BigDecimal newBlocked = userWallet.getBlockedFunds().subtract(BigDecimal.valueOf(behalfAmount));
                             userWallet.setBlockedFunds(newBlocked);
-                            createUserBill(userId, billing.getDdId(),"5", BigDecimal.valueOf(behalfAmount), newBlocked,user.getUserType(),"release blocked founds",null);
+                            createUserBill(userId, billing.getDdId(), "5", BigDecimal.valueOf(behalfAmount), newBlocked, user.getUserType(), "release blocked founds", null);
                         }
                     }
 
@@ -250,12 +277,23 @@ public class WalletService {
                     userWallet.setVersion(userWallet.getVersion() + 1);
 
                     boolean updateSuccess = userWalletService.update(userWallet, updateQuery);
-                    createUserBill(billing,userWallet.getBalanceWallet());
+                    createUserBill(billing, userWallet.getBalanceWallet());
                     if (!updateSuccess) {
                         throw new ServiceException(MessageUtils.message("no.wallet.update.faile"));
                     }
+                    releaseInFinally = false;
+                    TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronization() {
+                        @Override
+                        public void afterCommit() {
+                            if (lock.isHeldByCurrentThread()) {
+                                lock.unlock();
+                            }
+                        }
+                    });
                 } finally {
-                    lock.unlock();
+                    if (releaseInFinally && lock.isHeldByCurrentThread()) {
+                        lock.unlock();
+                    }
                 }
             } else {
                 throw new ServiceException(MessageUtils.message("no.system.busy.try.again"));
@@ -269,17 +307,17 @@ public class WalletService {
     /**
      * 增加余额
      *
-     * @param userId  用户ID
-     * @param amount  增加金额
+     * @param userId 用户ID
+     * @param amount 增加金额
      */
     @Transactional(rollbackFor = Exception.class)
-    public void addBalance(Long userId,String ddId,String type, BigDecimal amount,BigDecimal behalfAmount) {
+    public void addBalance(Long userId, String ddId, String type, BigDecimal amount, BigDecimal behalfAmount) {
         // 1. 参数校验
         if (userId == null || amount == null || amount.compareTo(BigDecimal.ZERO) <= 0) {
             throw new ServiceException(MessageUtils.message("no.wallet.common.cs.error"));
         }
-        InfoUser user=userService.getById(userId);
-        if(user==null){
+        InfoUser user = userService.getById(userId);
+        if (user == null) {
             throw new ServiceException(MessageUtils.message("no.wallet.noexist.userinfo"));
         }
         String lockKey = ConstantUtil.WalletBalanceLock + userId;
@@ -288,6 +326,7 @@ public class WalletService {
         try {
             // 尝试获取锁
             if (lock.tryLock(LOCK_WAIT_TIME, LOCK_TIMEOUT, TimeUnit.SECONDS)) {
+                boolean releaseInFinally = true;
                 try {
                     // 2. 获取用户钱包
                     LambdaQueryWrapper<UserWallet> walletQuery = new LambdaQueryWrapper<>();
@@ -307,20 +346,31 @@ public class WalletService {
                     userWallet.setBalanceWallet(newBalance);
                     userWallet.setVersion(userWallet.getVersion() + 1);
                     //该订单存在冻结金额,解冻金额
-                    long blockedCount=billingService.count(new LambdaQueryWrapper<UserBilling>().eq(UserBilling::getUserId, userId).eq(UserBilling::getDdId,ddId).eq(UserBilling::getType,"4"));
-                    if(blockedCount>0){
-                        BigDecimal newBlocked= userWallet.getBlockedFunds().subtract(behalfAmount);
+                    long blockedCount = billingService.count(new LambdaQueryWrapper<UserBilling>().eq(UserBilling::getUserId, userId).eq(UserBilling::getDdId, ddId).eq(UserBilling::getType, "4"));
+                    if (blockedCount > 0) {
+                        BigDecimal newBlocked = userWallet.getBlockedFunds().subtract(behalfAmount);
                         userWallet.setBlockedFunds(newBlocked);
-                        createUserBill(userId, ddId,"5", behalfAmount, newBlocked,user.getUserType(),"release blocked founds",null);
+                        createUserBill(userId, ddId, "5", behalfAmount, newBlocked, user.getUserType(), "release blocked founds", null);
                     }
                     boolean updateSuccess = userWalletService.update(userWallet, updateQuery);
-                    createUserBill(userId, ddId,type, amount, userWallet.getBalanceWallet(),user.getUserType(),"",behalfAmount);
+                    createUserBill(userId, ddId, type, amount, userWallet.getBalanceWallet(), user.getUserType(), "", behalfAmount);
 
                     if (!updateSuccess) {
                         throw new ServiceException(MessageUtils.message("no.wallet.update.faile"));
                     }
+                    releaseInFinally = false;
+                    TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronization() {
+                        @Override
+                        public void afterCommit() {
+                            if (lock.isHeldByCurrentThread()) {
+                                lock.unlock();
+                            }
+                        }
+                    });
                 } finally {
-                    lock.unlock();
+                    if (releaseInFinally && lock.isHeldByCurrentThread()) {
+                        lock.unlock();
+                    }
                 }
             } else {
                 throw new ServiceException(MessageUtils.message("no.system.busy.try.again"));
@@ -334,18 +384,18 @@ public class WalletService {
     /**
      * 扣除余额
      *
-     * @param userId  用户ID
-     * @param ddId    订单ID
-     * @param amount  扣除金额
+     * @param userId 用户ID
+     * @param ddId   订单ID
+     * @param amount 扣除金额
      */
     @Transactional(rollbackFor = Exception.class)
-    public void deductBalance(Long userId, String ddId, BigDecimal amount,String remark,String type) {
+    public void deductBalance(Long userId, String ddId, BigDecimal amount, String remark, String type) {
         // 1. 参数校验
         if (userId == null || ddId == null || amount == null || amount.compareTo(BigDecimal.ZERO) <= 0) {
             throw new ServiceException(MessageUtils.message("no.wallet.common.cs.error"));
         }
-        InfoUser user=userService.getById(userId);
-        if(user==null){
+        InfoUser user = userService.getById(userId);
+        if (user == null) {
             throw new ServiceException(MessageUtils.message("no.wallet.noexist.userinfo"));
         }
         String lockKey = ConstantUtil.WalletBalanceLock + userId;
@@ -353,6 +403,7 @@ public class WalletService {
         try {
             // 尝试获取锁
             if (lock.tryLock(LOCK_WAIT_TIME, LOCK_TIMEOUT, TimeUnit.SECONDS)) {
+                boolean releaseInFinally = true;
                 try {
                     // 2. 获取用户钱包
                     UserWallet userWallet = getUserWallet(userId);
@@ -376,9 +427,20 @@ public class WalletService {
                         throw new ServiceException(MessageUtils.message("no.wallet.update.faile"));
                     }
                     // 6. 钱包更新成功后再创建账单记录
-                    createUserBill(userId, ddId,type, amount, newBalance,user.getUserType(),remark,null);
+                    createUserBill(userId, ddId, type, amount, newBalance, user.getUserType(), remark, null);
+                    releaseInFinally = false;
+                    TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronization() {
+                        @Override
+                        public void afterCommit() {
+                            if (lock.isHeldByCurrentThread()) {
+                                lock.unlock();
+                            }
+                        }
+                    });
                 } finally {
-                    lock.unlock();
+                    if (releaseInFinally && lock.isHeldByCurrentThread()) {
+                        lock.unlock();
+                    }
                 }
             } else {
                 throw new ServiceException(MessageUtils.message("no.system.busy.try.again"));
@@ -411,27 +473,28 @@ public class WalletService {
     /**
      * 增加冻结金额(不回滚外层事务)
      *
-     * @param userId  用户ID
-     * @param amount  增加金额
+     * @param userId 用户ID
+     * @param amount 增加金额
      */
     @Transactional(propagation = Propagation.REQUIRES_NEW, rollbackFor = Exception.class)
-    public void addBlockFunds(Long userId, BigDecimal amount,String ddId) {
-        addBlockedFundsDetail(userId,amount,ddId);
+    public void addBlockFunds(Long userId, BigDecimal amount, String ddId) {
+        addBlockedFundsDetail(userId, amount, ddId);
     }
 
     /**
      * 解冻冻结金额不操作钱包余额
+     *
      * @param userId
      * @param amount
      * @param ddId
      */
-    public void deduceBlocked(Long userId, BigDecimal amount,String ddId) {
+    public void deduceBlocked(Long userId, BigDecimal amount, String ddId) {
         // 1. 参数校验
         if (userId == null || amount == null || amount.compareTo(BigDecimal.ZERO) <= 0) {
             throw new ServiceException(MessageUtils.message("no.wallet.common.cs.error"));
         }
-        InfoUser user=userService.getById(userId);
-        if(user==null){
+        InfoUser user = userService.getById(userId);
+        if (user == null) {
             throw new ServiceException(MessageUtils.message("no.wallet.noexist.userinfo"));
         }
 
@@ -440,6 +503,7 @@ public class WalletService {
         try {
             // 尝试获取锁
             if (lock.tryLock(LOCK_WAIT_TIME, LOCK_TIMEOUT, TimeUnit.SECONDS)) {
+                boolean releaseInFinally = true;
                 try {
                     // 2. 获取用户钱包
                     LambdaQueryWrapper<UserWallet> walletQuery = new LambdaQueryWrapper<>();
@@ -448,9 +512,9 @@ public class WalletService {
                     if (userWallet == null) {
                         throw new ServiceException(MessageUtils.message("no.user.wallet.not.exist"));
                     }
-                    BigDecimal balance= userWallet.getBlockedFunds().subtract(amount);
+                    BigDecimal balance = userWallet.getBlockedFunds().subtract(amount);
                     //钱包余额小于订单需要冻结的金额
-                    if(balance.compareTo(BigDecimal.ZERO) < 0){
+                    if (balance.compareTo(BigDecimal.ZERO) < 0) {
                         throw new ServiceException(MessageUtils.message("no.wallet.blockamount.jd.exception.message"));
                     }
                     // 3. 更新余额
@@ -463,12 +527,23 @@ public class WalletService {
                     userWallet.setBlockedFunds(newBalance);
                     userWallet.setVersion(userWallet.getVersion() + 1);
                     boolean updateSuccess = userWalletService.update(userWallet, updateQuery);
-                    createUserBill(userId,ddId,"5", amount,newBalance,user.getUserType(),"release blocked founds",null);
+                    createUserBill(userId, ddId, "5", amount, newBalance, user.getUserType(), "release blocked founds", null);
                     if (!updateSuccess) {
                         throw new ServiceException(MessageUtils.message("no.wallet.update.faile"));
                     }
+                    releaseInFinally = false;
+                    TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronization() {
+                        @Override
+                        public void afterCommit() {
+                            if (lock.isHeldByCurrentThread()) {
+                                lock.unlock();
+                            }
+                        }
+                    });
                 } finally {
-                    lock.unlock();
+                    if (releaseInFinally && lock.isHeldByCurrentThread()) {
+                        lock.unlock();
+                    }
                 }
             } else {
                 throw new ServiceException(MessageUtils.message("no.system.busy.try.again"));
@@ -481,22 +556,23 @@ public class WalletService {
 
     /**
      * 回滚外层事务
+     *
      * @param userId
      * @param amount
      * @param ddId
      */
     @Transactional(rollbackFor = Exception.class)
-    public void addBlockFundsBackTransaction(Long userId, BigDecimal amount,String ddId) {
-        addBlockedFundsDetail(userId,amount,ddId);
+    public void addBlockFundsBackTransaction(Long userId, BigDecimal amount, String ddId) {
+        addBlockedFundsDetail(userId, amount, ddId);
     }
 
-    private void addBlockedFundsDetail(Long userId, BigDecimal amount,String ddId) {
+    private void addBlockedFundsDetail(Long userId, BigDecimal amount, String ddId) {
         // 1. 参数校验
         if (userId == null || amount == null || amount.compareTo(BigDecimal.ZERO) <= 0) {
             throw new ServiceException(MessageUtils.message("no.wallet.common.cs.error"));
         }
-        InfoUser user=userService.getById(userId);
-        if(user==null){
+        InfoUser user = userService.getById(userId);
+        if (user == null) {
             throw new ServiceException(MessageUtils.message("no.wallet.noexist.userinfo"));
         }
 
@@ -506,6 +582,7 @@ public class WalletService {
         try {
             // 尝试获取锁
             if (lock.tryLock(LOCK_WAIT_TIME, LOCK_TIMEOUT, TimeUnit.SECONDS)) {
+                boolean releaseInFinally = true;
                 try {
                     // 2. 获取用户钱包
                     LambdaQueryWrapper<UserWallet> walletQuery = new LambdaQueryWrapper<>();
@@ -514,11 +591,11 @@ public class WalletService {
                     if (userWallet == null) {
                         throw new ServiceException(MessageUtils.message("no.user.wallet.not.exist"));
                     }
-                    BigDecimal balance= userWallet.getBalanceWallet().subtract(userWallet.getBlockedFunds()).subtract(amount);
+                    BigDecimal balance = userWallet.getBalanceWallet().subtract(userWallet.getBlockedFunds()).subtract(amount);
                     //钱包余额小于订单需要冻结的金额
-                    if(balance.compareTo(BigDecimal.ZERO) < 0){
-                        String message=MessageUtils.message("no.wallet.balance.less.than.order.amount");
-                        message= StrUtil.format(message,amount);
+                    if (balance.compareTo(BigDecimal.ZERO) < 0) {
+                        String message = MessageUtils.message("no.wallet.balance.less.than.order.amount");
+                        message = StrUtil.format(message, amount);
                         throw new ServiceException(message);
                     }
                     // 3. 更新余额
@@ -532,12 +609,23 @@ public class WalletService {
                     userWallet.setBlockedFunds(newBalance);
                     userWallet.setVersion(userWallet.getVersion() + 1);
                     boolean updateSuccess = userWalletService.update(userWallet, updateQuery);
-                    createUserBill(userId,ddId,"4", amount,newBalance,user.getUserType(),"blocked funds",null);
+                    createUserBill(userId, ddId, "4", amount, newBalance, user.getUserType(), "blocked funds", null);
                     if (!updateSuccess) {
                         throw new ServiceException(MessageUtils.message("no.wallet.update.faile"));
                     }
+                    releaseInFinally = false;
+                    TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronization() {
+                        @Override
+                        public void afterCommit() {
+                            if (lock.isHeldByCurrentThread()) {
+                                lock.unlock();
+                            }
+                        }
+                    });
                 } finally {
-                    lock.unlock();
+                    if (releaseInFinally && lock.isHeldByCurrentThread()) {
+                        lock.unlock();
+                    }
                 }
             } else {
                 throw new ServiceException(MessageUtils.message("no.system.busy.try.again"));
@@ -549,9 +637,6 @@ public class WalletService {
     }
 
 
-
-
-
     /**
      * 创建积分流水
      */
@@ -572,9 +657,9 @@ public class WalletService {
         pointsTransactionService.save(pointsTransaction);
     }
 
-    private void createUserBill(Long userId,String ddId,String type,BigDecimal change,BigDecimal current,String userType,String remark,BigDecimal behalfAmount){
+    private void createUserBill(Long userId, String ddId, String type, BigDecimal change, BigDecimal current, String userType, String remark, BigDecimal behalfAmount) {
         try {
-            UserBilling bill=new UserBilling();
+            UserBilling bill = new UserBilling();
             bill.setUserId(userId);
             bill.setType(type);
             bill.setState("0");
@@ -584,17 +669,17 @@ public class WalletService {
             bill.setWalletBalance(current);
             bill.setCretim(new Date());
             bill.setIllustrate(remark);
-            if(behalfAmount!=null){
+            if (behalfAmount != null) {
                 bill.setBehalfAmount(behalfAmount.doubleValue());
             }
             billingService.saveOrUpdate(bill);
-        }catch (Exception e){
+        } catch (Exception e) {
             System.out.println(e.getMessage());
         }
 
     }
 
-    private void createUserBill(UserBilling bill,BigDecimal current){
+    private void createUserBill(UserBilling bill, BigDecimal current) {
         bill.setWalletBalance(current);
         billingService.saveOrUpdate(bill);
     }