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



大家好! :)

我有以下情况 两张桌子 -AccountTransaction想法很简单 - 在两个帐户之间创建交易时(场景是仅涉及 2 个帐户(

- sender new balance = senderAccountBalance - transactionAmount
- receiver new balance = receiverAccountBalance + transactionAmount

(我正在扩展 JpaRepository(

执行@PostMapping("/transactions")方法既不会更改SenderAccount Balance属性也不会更改ReceiverAccount Balance属性 - 下面是Controller方法的代码和Entities我需要修复此选项或找出另一个选项,因为我现在有点卡住了:{

@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();
}

帐户.class

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;
}
}

交易.class

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();
}
}

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

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

否则,存储库将返回处于分离状态的实体(不跟踪修改(,要保存修改,您必须通过调用repository.save(entity)来显式保存它们。喜欢这个:

@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();
}

使用事务方法会改变此行为,并且存储库返回处于附加状态的实体,这意味着Hibernate将跟踪这些实体中的所有更改,并且所有更新将在方法结束时发送到DB。要具有此行为,您必须将此方法标记为@Transactional

@PostMapping("/transactions")
@Transactional
public ResponseEntity<Transaction> createTransaction(@Valid @RequestBody Transaction transaction) {
...