🎨 交易功能代码优化
This commit is contained in:
parent
f1a739e73b
commit
c2651d0ad4
@ -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;
|
||||||
|
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
@ -18,41 +18,63 @@ 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());
|
||||||
|
lock.lock();
|
||||||
|
try {
|
||||||
// 判断发起者账户状态
|
// 判断发起者账户状态
|
||||||
boolean formAccountStatus = checkFormAccountStatus(transactionRecord.getFormBankAccount(), transactionRecord.getMoney());
|
boolean formAccountStatus = checkFormAccountStatus(transactionRecord.getFormBankAccount(), transactionRecord.getMoney());
|
||||||
if (formAccountStatus) {
|
boolean toAccountStatus = checkFormAccountStatus(transactionRecord.getToBankAccount(), BigDecimal.valueOf(0));
|
||||||
Integer result = transactionRecordMapper.transfer(transactionRecord.getFormBankAccount(), transactionRecord.getToBankAccount(), transactionRecord.getMoney());
|
if (formAccountStatus && toAccountStatus) {
|
||||||
|
Integer result = transactionRecordMapper.debit(transactionRecord.getFormBankAccount(), transactionRecord.getMoney());
|
||||||
|
if (result > 0) {
|
||||||
|
result = transactionRecordMapper.credit(transactionRecord.getToBankAccount(), transactionRecord.getMoney());
|
||||||
if (result > 0) {
|
if (result > 0) {
|
||||||
transactionRecord.setTransactionNo(nextTransactionNo());
|
transactionRecord.setTransactionNo(nextTransactionNo());
|
||||||
transactionRecord.setTransactionTime(new Date());
|
transactionRecord.setTransactionTime(new Date());
|
||||||
transactionRecordMapper.insertSelective(transactionRecord);
|
transactionRecordMapper.insertSelective(transactionRecord);
|
||||||
}
|
|
||||||
} else {
|
|
||||||
throw new TransactionException(TransactionCode.INSUFFICIENT_BALANCE);
|
|
||||||
}
|
|
||||||
return transactionRecord;
|
return transactionRecord;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
} else if (toAccountStatus) {
|
||||||
|
throw new TransactionException(TransactionCode.INSUFFICIENT_BALANCE);
|
||||||
|
} else {
|
||||||
|
throw new TransactionException(TransactionCode.UNKNOWN_ACCOUNT);
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<TransactionRecordDTO> findTransactionRecords(String bankAccount, String startDate, String endDate) {
|
public List<TransactionRecordDTO> findTransactionRecords(String bankAccount, String startDate, String endDate) {
|
||||||
@ -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;
|
||||||
}
|
}
|
||||||
|
@ -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 *
|
||||||
|
Loading…
Reference in New Issue
Block a user