【问题标题】:Spring @Transactional method issueSpring @Transactional 方法问题
【发布时间】:2019-09-01 09:29:02
【问题描述】:

所以,我有一个控制器 [POST] 方法,它基本上应该创建一个 transaction

逻辑很简单,同时创建transaction 两个帐户 应该涉及(这是场景),进入transaction 我正在传递3个字段 - amountemitterId 和 @987654327 @。创建事务后,senderBalance 应减少transaction.amount,receiverBalance 应增加transaction.amount,但由于某种原因没有任何变化

代码如下:

@Autowired
    private AccountRepository accountRepository;

    @Autowired
    private TransactionRepository transactionRepository;

@Transactional
    @PostMapping("/transactions")
    public ResponseEntity<Transaction> createTransaction(@Valid @RequestBody Transaction transaction) {
        final Transaction result = transactionRepository.save(transaction);
        final URI location = ServletUriComponentsBuilder.fromCurrentRequest().
                path("/{id}")
                .buildAndExpand(result.getId()).toUri();
        Integer emitterBalance = accountRepository.findById(result.getSenderAccountId()).get().getBalance();
        Integer receptorBalance = accountRepository.findById(result.getReceiverAccountId()).get().getBalance();
        Integer amount = transactionRepository.findById(result.getId()).get().getAmount();
        Integer emitterFinalBalance = emitterBalance - amount;
        Integer receptorFinalBalance = receptorBalance + amount;
        accountRepository.findById(result.getSenderAccountId()).get().setBalance(emitterFinalBalance);
        accountRepository.findById(result.getReceiverAccountId()).get().setBalance(receptorFinalBalance);
        transactionRepository.save(result);
        transactionRepository.save(transaction);
        return ResponseEntity.created(location).build();
    }

实体 交易

public class Transaction {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @NotNull
    private Integer amount;
    private Instant created;
    private Long senderAccountId;
    private Long receiverAccountId;

    @JsonIgnore
    @ManyToOne
    @JoinColumn(name = "emitterId")
    private Account emitterId;

    @JsonIgnore
    @ManyToOne
    @JoinColumn(name = "receptorId")
    private Account receptorId;

    public Transaction(Integer amount, Account emitterId, Account receptorId){
        this.created = Instant.now();
        this.amount = amount;
        this.emitterId = emitterId;
        this.receptorId = receptorId;
        senderAccountId = this.emitterId.getId();
        receiverAccountId = this.receptorId.getId();
    }

}

帐户

public class Account {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @NotNull
    private String holder;

    @NotNull
    private Integer balance;

    @OneToMany(mappedBy = "emitterId",fetch = FetchType.LAZY,cascade = CascadeType.ALL)
    private List<Transaction> transactionsMade;

    @OneToMany(mappedBy = "receptorId",fetch = FetchType.LAZY,cascade = CascadeType.ALL)
    private List<Transaction> transactionsReceived;

    public Account(String holder, Integer balance){
        this.holder = holder;
        this.balance = balance;
    }

    public Account(Long id){
        this.id = id;
    }

}

你能帮我解决这个问题吗?:)?

谢谢你!

【问题讨论】:

  • 能否请您在控制器中提供您的 transactionRepository 声明。
  • 请稍等,我会在 30 秒内更新代码
  • 你在你的方法中究竟在哪里改变resulttransaction的值?

标签: java database hibernate transactions h2


【解决方案1】:

看起来您没有保留更新余额的帐户对象。您是否有从交易到具有级联的个人帐户的实体映射,以便在保存交易后相应的帐户对象也被持久化。

【讨论】:

  • 我会用两个实体类更新主代码,请看一下:)
  • accountRepository.findById(result.getSenderAccountId()).get().setBalance(emitterFinalBalance); accountRepository.findById(result.getReceiverAccountId()).get().setBalance(receptorFinalBalance); 而不是上面两行,试试result.getSenderAccountId().setBalance(emitterFinalBalance); result.getReceiverAccountId().setBalance(receptorFinalBalance);
  • 现在有这个问题:现在它归咎于这一行: Integer emitBalance = accountRepository.findById(result.getSenderAccountId()).get().getBalance();出现异常:“给定的 id 不能为空!;嵌套异常是 java.lang.IllegalArgumentException:给定的 id 不能为空!”
  • 是的,我已经解决了主要的持久性问题 :) 谢谢!
【解决方案2】:

尝试以下操作:

    accountRepository.findById(result.getSenderAccountId()).get().setBalance(emitterFinalBalance);

accountRepository.findById(result.getReceiverAccountId()).get().setBalance(receptorFinalBalance);

替换为

Account sender = accountRepository.findById(result.getSenderAccountId()).get();
sender.setBalance(emitterFinalBalance);
accountRepository.save(sender);

Account receiver = accountRepository.findById(result.getReceiverAccountId()).get();
receiver.setBalance(receptorFinalBalance);
accountRepository.save(receiver);

【讨论】:

  • 现在它归咎于这一行: Integer emitBalance = accountRepository.findById(result.getSenderAccountId()).get().getBalance();出现异常:“给定的 id 不能为空!;嵌套异常是 java.lang.IllegalArgumentException:给定的 id 不能为空!”,
  • 你能放置断点并检查传入参数“transaction”是否有senderAccountId?我无法理解我提议的更改如何导致此错误。
  • Nono,我刚刚发现这不是由您提出的更改引起的。那是以前的事情。附言交易只有“id”和“amount”,但 senderAccountId 为空:/
  • P.S.没关系,我将emitterId 和receptorId 传递到post requestbody,现在传递senderAcconutId 和receiverAccountId 以及它的罚款
  • 顺便说一句,如果你能看看我关于同一主题的 anotehr 问题。链接:stackoverflow.com/questions/57746512/…
猜你喜欢
  • 1970-01-01
  • 2017-06-18
  • 1970-01-01
  • 2012-08-07
  • 2018-02-26
  • 2015-02-23
  • 1970-01-01
  • 2019-02-15
  • 2013-01-06
相关资源
最近更新 更多