未对@Transactional注释执行回滚

时间:2019-09-12 10:38:44

标签: spring spring-boot jpa transactions

我正在尝试创建用于转移资金的API 即提款和存款。 我使用@Transactional Annotation执行了事务。  但是有某些标准,即如果不存在银行帐号,则应通过运行时异常进行。 我将在其中附加代码。现在,当调用transferBalanceMethod时,如果存户银行帐户不存在,则撤回的金额也应回滚。 但这并没有发生。意味着当资金从账户A到账户B的转帐金额为1000卢比时,如果B的存入出现异常,则也应提取A账户的提款。 我也尝试了@Transactional注解以及Exception类的rollbackFor属性 我也尝试为存款和取款方法添加@Transaction批注,但是我们使用同一笔交易,因为我们使用的是必需传播**

Model Class//This is the Model Class
//All Imports

@Entity
public class BankAccount {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    @Column(name = "id")
    private Integer id;

    @Column(name = "bankAccountNumber", nullable = false,unique = true)
    @NotNull
    @Size(min = 5, message = "Bank account number should be greater than 5 characters")
    private String bankAccountNumber;

    @NotNull
    @Column(name = "balance", nullable = false)
    @Min(1000)
    private Long balance;

//Getter Setter and Constructor

**Controller File**//This is the Controller Class

//All imports and other stuff such as @RestController, @Autowired   

@GetMapping("/bankaccount/transfer")
public void transferBalance(@RequestParam("bankAccountNo1") String bankAccountNo1, @RequestParam("bankAccountNo2") String bankAccountNo2,
            @RequestParam("balance") Long balance) throws RuntimeException
    {
        bankService.transferBalance(bankAccountNo1,bankAccountNo2, balance);
    }

}

**Service File:-**//This is Service Layer
//All imports

@Service
public class BankService {

    @Autowired
    private BankRepository bankRepository;

    @Autowired
    private ModelMapper modelMapper;

    public List<BankAccountDTO> getAllBankAccount() {
        List<BankAccountDTO> bankAccountDTO = new ArrayList<BankAccountDTO>();
        List<BankAccount> bankAccount = bankRepository.findAll();
        for (BankAccount b : bankAccount) {
            bankAccountDTO.add(modelMapper.map(b, BankAccountDTO.class));
        }
        return bankAccountDTO;
    }

    public ResponseEntity<?> getIndividualBankAccount(String bankAccountNumber) {
        BankAccount bankAccount = bankRepository.findByBankAccountNumber(bankAccountNumber);
        if (bankAccount == null) {
            return new ResponseEntity<>("Account not found", HttpStatus.BAD_REQUEST);
        } else {
            return new ResponseEntity<>(
                    modelMapper.map(bankRepository.findByBankAccountNumber(bankAccountNumber), BankAccountDTO.class),
                    HttpStatus.OK);
        }
    }

    public Object addBankAccount(BankAccountDTO bankAccountDTO) {
        return bankRepository.save(modelMapper.map(bankAccountDTO, BankAccount.class));
    }

    @Transactional(propagation = Propagation.REQUIRED)
    public void depositBalance(String bankAccountNumber, Long balance) throws RuntimeException {
        BankAccount bankAccNo = bankRepository.findByBankAccountNumber(bankAccountNumber);

        if (bankAccNo == null) {
            throw new RuntimeException("Bank Accout Number is not found : " + bankAccountNumber);
        } else {
            if (balance <= 0) {
                throw new RuntimeException("Please deposit appropriate balance");
            } else {
                Long amount = bankAccNo.getBalance() + balance;
                bankAccNo.setBalance(amount);
                bankRepository.save(bankAccNo);
            }
        }

    }

    @Transactional(propagation = Propagation.REQUIRED)
    public void withdrawBalance(String bankAccountNumber, Long balance) throws RuntimeException {
        BankAccount bankAccNo = bankRepository.findByBankAccountNumber(bankAccountNumber);
        if (bankAccNo == null) {
            throw new RuntimeException("Bank Account not found :" + bankAccountNumber);
        } else {
            if (balance <= 0) {
                throw new RuntimeException("Please withdraw appropriate balance");
            } else {
                Long amount = bankAccNo.getBalance() - balance;
                if (amount < 1000) {
                    throw new RuntimeException("Sorry Cannot withdraw.Your minimum balance should be thousand rupees!");
                } else {
                    bankAccNo.setBalance(amount);
                    bankRepository.save(bankAccNo);
                }
            }
        }
    }

    @Transactional(propagation = Propagation.REQUIRES_NEW, rollbackFor = RuntimeException.class)
    public void transferBalance(String bankAccountNo1, String bankAccountNo2, Long balance) throws RuntimeException {
        try {
            withdrawBalance(bankAccountNo1, balance);
            depositBalance(bankAccountNo2, balance);

        } catch (RuntimeException e) {
            throw e;
        }

    }

}

1 个答案:

答案 0 :(得分:0)

只有运行时异常会在spring事务注释中触发回滚操作,如果您使用自定义注释,则需要确保从RuntimeException进行扩展,或者向您的事务添加特定的rollback子句以使其回滚该特定例外。

也许这个答案对您有用: Spring transaction: rollback on Exception or Throwable

也可以在这里转到spring的官方交易文档: https://docs.spring.io/spring/docs/4.2.x/spring-framework-reference/html/transaction.html

相关问题