🎨 交易功能代码优化

This commit is contained in:
ronger 2023-02-08 16:33:19 +08:00
parent f1a739e73b
commit c2651d0ad4
4 changed files with 55 additions and 24 deletions

View File

@ -6,7 +6,8 @@ package com.rymcu.forest.enumerate;
public enum TransactionCode { public enum TransactionCode {
INSUFFICIENT_BALANCE(901, "余额不足"), INSUFFICIENT_BALANCE(901, "余额不足"),
UNKNOWN_ACCOUNT(902, "账号不存在"); UNKNOWN_ACCOUNT(902, "账号不存在"),
FAIL(903, "交易失败");
private int code; private int code;

View File

@ -16,11 +16,10 @@ public interface TransactionRecordMapper extends Mapper<TransactionRecord> {
* 交易 * 交易
* *
* @param formBankAccount * @param formBankAccount
* @param toBankAccount
* @param money * @param money
* @return * @return
*/ */
Integer transfer(@Param("formBankAccount") String formBankAccount, @Param("toBankAccount") String toBankAccount, @Param("money") BigDecimal money); Integer debit(@Param("formBankAccount") String formBankAccount, @Param("money") BigDecimal money);
/** /**
* 查询指定账户的交易记录 * 查询指定账户的交易记录
@ -48,4 +47,11 @@ public interface TransactionRecordMapper extends Mapper<TransactionRecord> {
* @return * @return
*/ */
Boolean existsWithNewbieRewards(@Param("bankAccount") String bankAccount); Boolean existsWithNewbieRewards(@Param("bankAccount") String bankAccount);
/**
* @param toBankAccount
* @param money
* @return
*/
Integer credit(@Param("toBankAccount") String toBankAccount, @Param("money") BigDecimal money);
} }

View File

@ -18,40 +18,62 @@ import org.springframework.transaction.annotation.Transactional;
import javax.annotation.Resource; import javax.annotation.Resource;
import java.math.BigDecimal; import java.math.BigDecimal;
import java.util.Calendar; import java.util.*;
import java.util.Date; import java.util.concurrent.locks.ReentrantLock;
import java.util.List;
import java.util.Objects;
/** /**
* @author ronger * @author ronger
*/ */
@Service @Service
public class TransactionRecordServiceImpl extends AbstractService<TransactionRecord> implements TransactionRecordService { public class TransactionRecordServiceImpl extends AbstractService<TransactionRecord> implements TransactionRecordService {
@Resource @Resource
private TransactionRecordMapper transactionRecordMapper; private TransactionRecordMapper transactionRecordMapper;
@Resource @Resource
private BankAccountMapper bankAccountMapper; private BankAccountMapper bankAccountMapper;
@Resource @Resource
private RedisService redisService; private RedisService redisService;
private final Map<String, ReentrantLock> userTransferLocks = new HashMap<>();
@Override @Override
@Transactional(rollbackFor = Exception.class) @Transactional(rollbackFor = Exception.class)
public TransactionRecord transfer(TransactionRecord transactionRecord) { public TransactionRecord transfer(TransactionRecord transactionRecord) {
// 判断发起者账户状态 ReentrantLock lock = getUserTransferLocks(transactionRecord.getFormBankAccount());
boolean formAccountStatus = checkFormAccountStatus(transactionRecord.getFormBankAccount(), transactionRecord.getMoney()); lock.lock();
if (formAccountStatus) { try {
Integer result = transactionRecordMapper.transfer(transactionRecord.getFormBankAccount(), transactionRecord.getToBankAccount(), transactionRecord.getMoney()); // 判断发起者账户状态
if (result > 0) { boolean formAccountStatus = checkFormAccountStatus(transactionRecord.getFormBankAccount(), transactionRecord.getMoney());
transactionRecord.setTransactionNo(nextTransactionNo()); boolean toAccountStatus = checkFormAccountStatus(transactionRecord.getToBankAccount(), BigDecimal.valueOf(0));
transactionRecord.setTransactionTime(new Date()); if (formAccountStatus && toAccountStatus) {
transactionRecordMapper.insertSelective(transactionRecord); Integer result = transactionRecordMapper.debit(transactionRecord.getFormBankAccount(), transactionRecord.getMoney());
if (result > 0) {
result = transactionRecordMapper.credit(transactionRecord.getToBankAccount(), transactionRecord.getMoney());
if (result > 0) {
transactionRecord.setTransactionNo(nextTransactionNo());
transactionRecord.setTransactionTime(new Date());
transactionRecordMapper.insertSelective(transactionRecord);
return transactionRecord;
}
}
} else if (toAccountStatus) {
throw new TransactionException(TransactionCode.INSUFFICIENT_BALANCE);
} else {
throw new TransactionException(TransactionCode.UNKNOWN_ACCOUNT);
} }
} else { } finally {
throw new TransactionException(TransactionCode.INSUFFICIENT_BALANCE); lock.unlock();
}
throw new TransactionException(TransactionCode.FAIL);
}
private ReentrantLock getUserTransferLocks(String formBankAccount) {
synchronized (userTransferLocks) {
ReentrantLock lock = userTransferLocks.get(formBankAccount);
if (lock == null) {
lock = new ReentrantLock();
userTransferLocks.put(formBankAccount, lock);
}
return lock;
} }
return transactionRecord;
} }
@Override @Override
@ -162,7 +184,7 @@ public class TransactionRecordServiceImpl extends AbstractService<TransactionRec
private boolean checkFormAccountStatus(String formBankAccount, BigDecimal money) { private boolean checkFormAccountStatus(String formBankAccount, BigDecimal money) {
BankAccount bankAccount = findInfoByBankAccount(formBankAccount); BankAccount bankAccount = findInfoByBankAccount(formBankAccount);
if (Objects.nonNull(bankAccount)) { if (Objects.nonNull(bankAccount)) {
return bankAccount.getAccountBalance().compareTo(money) > 0; return bankAccount.getAccountBalance().compareTo(money) >= 0;
} }
return false; return false;
} }

View File

@ -11,13 +11,15 @@
<result column="transaction_type" property="transactionType"></result> <result column="transaction_type" property="transactionType"></result>
<result column="transaction_time" property="transactionTime"></result> <result column="transaction_time" property="transactionTime"></result>
</resultMap> </resultMap>
<update id="transfer"> <update id="debit">
update forest_bank_account update forest_bank_account
set account_balance = account_balance - #{money} set account_balance = account_balance - #{money}
where bank_account = #{formBankAccount}; where bank_account = #{formBankAccount} and account_balance >= #{money}
</update>
<update id="credit">
update forest_bank_account update forest_bank_account
set account_balance = account_balance + #{money} set account_balance = account_balance + #{money}
where bank_account = #{toBankAccount}; where bank_account = #{toBankAccount}
</update> </update>
<select id="selectTransactionRecords" resultMap="DTOResultMap"> <select id="selectTransactionRecords" resultMap="DTOResultMap">
select * select *
@ -40,4 +42,4 @@
where to_bank_account = #{bankAccount} and funds = '新手奖励' where to_bank_account = #{bankAccount} and funds = '新手奖励'
limit 1), false) limit 1), false)
</select> </select>
</mapper> </mapper>