Senior
65
public class MoneyTransferService { /** * @param fromAccountId μοναδικός αναγνωριστικός κωδικός του χρήστη που μεταφέρει τα χρήματα * @param toAccountId μοναδικός αναγνωριστικός κωδικός του χρήστη στον οποίο μεταφέρονται τα χρήματα * @param amount ποσό μεταφοράς. Θετικός αριθμός */ @Transactional public void transferMoney(Long fromAccountId, Long toAccountId, BigDecimal amount) { if (amount.compareTo(BigDecimal.ZERO) <= 0) { throw new RuntimeException("Το ποσό πρέπει να είναι θετικό"); } if (fromAccountId.equals(toAccountId)) { throw new RuntimeException("Ο λογαριασμός δεν μπορεί να είναι ο ίδιος"); } Long firstId = Math.min(fromAccountId, toAccountId); Long secondId = Math.max(fromAccountId, toAccountId); Account first = accountRepository.findByIdForUpdate(firstId) .orElseThrow(() -> new RuntimeException("Ο λογαριασμός δεν βρέθηκε")); Account second = accountRepository.findByIdForUpdate(secondId) .orElseThrow(() -> new RuntimeException("Ο λογαριασμός δεν βρέθηκε")); Account from = fromAccountId.equals(firstId) ? first : second; Account to = fromAccountId.equals(firstId) ? second : first; if (from.getBalance().compareTo(amount) < 0) { throw new RuntimeException("Ανεπαρκές υπόλοιπο"); } from.setBalance(from.getBalance().subtract(amount)); to.setBalance(to.getBalance().add(amount)); accountRepository.save(to); accountRepository.save(from); } } @Entity @Data public class Account { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; private BigDecimal balance; }
Εταιρείες όπου ρωτήθηκαν
Απάντηση από AI
sobes.tech AI
В представленном коде есть несколько важных моментов и одна критическая ошибка:
- Проверка amount > 0 и что fromAccountId != toAccountId — правильные валидации.
- Для предотвращения дедлоков при конкурентных переводах используется упорядоченное блокирование счетов через findByIdForUpdate — хорошая практика.
- Ошибка в логике обновления балансов:
from.setBalance(from.getBalance().subtract(amount));
to.setBalance(from.getBalance().add(amount));
Здесь после вычитания amount из from.getBalance(), при вычислении нового баланса для to используется уже уменьшенный баланс from, а нужно прибавлять amount к текущему балансу to.
Правильно:
to.setBalance(to.getBalance().add(amount));
- Сохранение счетов через accountRepository.save() — корректно.
Итог: исправьте обновление баланса получателя, иначе деньги будут списываться, но не зачисляться.
Пример исправленного участка:
from.setBalance(from.getBalance().subtract(amount));
to.setBalance(to.getBalance().add(amount));