Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/spring/14.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 关于创建事务的控制器方法问题_Java_Spring_Hibernate_H2 - Fatal编程技术网

Java 关于创建事务的控制器方法问题

Java 关于创建事务的控制器方法问题,java,spring,hibernate,h2,Java,Spring,Hibernate,H2,大家好 我有以下几种情况 两个表-账户和交易 想法很简单——在两个账户之间创建交易时,唯一的问题是只涉及两个账户 - sender new balance = senderAccountBalance - transactionAmount - receiver new balance = receiverAccountBalance + transactionAmount 我正在扩展JpaRepositories 执行@PostMapping/transactions方法不会更改Sende

大家好

我有以下几种情况 两个表-账户和交易 想法很简单——在两个账户之间创建交易时,唯一的问题是只涉及两个账户

- sender new balance = senderAccountBalance - transactionAmount

- receiver new balance = receiverAccountBalance + transactionAmount
我正在扩展JpaRepositories

执行@PostMapping/transactions方法不会更改SenderAccount余额属性或ReceiverAccount余额属性-以下是控制器方法和实体的代码 我需要修复此选项或找到另一个选项,因为我现在有点卡住了:{

@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(transaction.getSenderAccountId()).get().getBalance();
        Integer receptorBalance = accountRepository.findById(transaction.getReceiverAccountId()).get().getBalance();
        Integer amount = transactionRepository.findById(transaction.getId()).get().getAmount();
        Integer emitterFinalBalance = emitterBalance - amount;
        Integer receptorFinalBalance = receptorBalance + amount;
        accountRepository.findById(transaction.getSenderAccountId()).get().setBalance(emitterFinalBalance);
        accountRepository.findById(transaction.getReceiverAccountId()).get().setBalance(receptorFinalBalance);
        return ResponseEntity.created(location).build();
    }
你能帮我解决这个问题吗? 感谢您的支持!:

只需将您的方法标记为@Transactional即可

否则,存储库将返回处于分离状态的实体。修改不会被跟踪,要保存修改,必须通过调用repository.saveentity显式保存它们。如下所示:

 @PostMapping("/transactions")
 public ResponseEntity<Transaction> createTransaction(@Valid @RequestBody Transaction transaction) {
   ...
   var senderAccount = accountRepository.findById(transaction.getSenderAccountId()).get();
   senderAccount.setBalance(emitterFinalBalance);
   accountRepository.save(senderAccount);

   var receiverAccount = accountRepository.findById(transaction.getReceiverAccountId()).get();
   receiverAccount.setBalance(receptorFinalBalance);
   accountRepository.save(receiverAccount);

   return ResponseEntity.created(location).build();
}

你的方法需要是事务性的。否则你只会修改分离的对象。请使用变量,不要调用Optional.get,并了解实体之间的关联:事务不应该有帐户ID。它应该有帐户本身。嘿,Max,谢谢你的回复,但我对这部分不太了解关于显式调用repository.saveentity-您能帮我修复代码的一部分来澄清这一点吗?@PavelS我已经用示例更新了答案,请看一看。请记住,只有@Transactional方法在单个事务中完成。如果方法不是事务性的,则每个DB操作都会保存一次在单独的事务中完成。
public class Transaction {

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

    @NotNull
    private Integer amount;

    @NotNull
    private Instant created;

    @NotNull
    private Long senderAccountId;

    @NotNull
    private Long receiverAccountId;

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

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

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

}
 @PostMapping("/transactions")
 public ResponseEntity<Transaction> createTransaction(@Valid @RequestBody Transaction transaction) {
   ...
   var senderAccount = accountRepository.findById(transaction.getSenderAccountId()).get();
   senderAccount.setBalance(emitterFinalBalance);
   accountRepository.save(senderAccount);

   var receiverAccount = accountRepository.findById(transaction.getReceiverAccountId()).get();
   receiverAccount.setBalance(receptorFinalBalance);
   accountRepository.save(receiverAccount);

   return ResponseEntity.created(location).build();
}
@PostMapping("/transactions")
@Transactional
public ResponseEntity<Transaction> createTransaction(@Valid @RequestBody Transaction transaction) {
    ...