🔧 Try To Use `savepoint` In Spring JPA/Hibernate
Nachrichtenbereich: 🔧 Programmierung
🔗 Quelle: dev.to
This article describes my failed attempt to use the PostgreSQL SAVEPOINT in Spring JPA.
About PostgreSQL SAVEPOINT.
EntityManager
@PersistenceContext
private EntityManager entityManager;
@Transactional(propagation=NESTED, isolation= READ_UNCOMMITTED)
public void transferWithSavePoint(String fromAccount, String toAccount, String anotherAccount,
double amount) throws SQLException {
// step 1
Account from = accountRepository.findByName(fromAccount);
Branch fromBranch = branchRepository.findByName(from.getBranchName());
from.setBalance(from.getBalance().subtract(BigDecimal.valueOf(amount)));
fromBranch.setBalance(fromBranch.getBalance().subtract(BigDecimal.valueOf(amount)));
accountRepository.save(from);
branchRepository.save(fromBranch);
Connection connection = entityManager.unwrap(SessionImpl.class).connection();
Savepoint savepoint = connection.setSavepoint();
// step 2
Account to = accountRepository.findByName(toAccount);
Branch toBranch = branchRepository.findByName(to.getBranchName());
to.setBalance(to.getBalance().add(BigDecimal.valueOf(amount)));
toBranch.setBalance(toBranch.getBalance().add(BigDecimal.valueOf(amount)));
accountRepository.save(to);
branchRepository.save(toBranch);
connection.rollback(savepoint);
// final step
Account finalAccount = accountRepository.findByName(anotherAccount);
Branch finalBranch = branchRepository.findByName(to.getBranchName());
finalAccount.setBalance(finalAccount.getBalance().add(BigDecimal.valueOf(amount)));
finalBranch.setBalance(finalBranch.getBalance().add(BigDecimal.valueOf(amount)));
accountRepository.save(finalAccount);
branchRepository.save(finalBranch);
}
I use Connection Pool in this project, so the connection created by EntityManager is different @Transactional
method’s connection
- savepoint: is before transferWithSavePoint
-
rollback: rollback to all of the operations before, so
STEP1
is rollback, butSTEP2
andFinal STEP
is done.
Next Try: AbstractTransactionStatus
@Autowired
private JdbcTemplate jdbcTemplate;
@Autowired
private TransactionTemplate transactionTemplate;
public void transferWithSavePoint(String fromAccount, String toAccount, String anotherAccount,
double amount) {
transactionTemplate.execute(status -> {
Account from = accountRepository.findByName(fromAccount);
Branch fromBranch = branchRepository.findByName(from.getBranchName());
from.setBalance(from.getBalance().subtract(BigDecimal.valueOf(amount)));
fromBranch.setBalance(fromBranch.getBalance().subtract(BigDecimal.valueOf(amount)));
accountRepository.save(from);
branchRepository.save(fromBranch);
Object savepoint = status.createSavepoint();
// step 2
Account to = accountRepository.findByName(toAccount);
Branch toBranch = branchRepository.findByName(to.getBranchName());
to.setBalance(to.getBalance().add(BigDecimal.valueOf(amount)));
toBranch.setBalance(toBranch.getBalance().add(BigDecimal.valueOf(amount)));
accountRepository.save(to);
branchRepository.save(toBranch);
status.rollbackToSavepoint(savepoint);
// final step
Account finalAccount = accountRepository.findByName(anotherAccount);
Branch finalBranch = branchRepository.findByName(to.getBranchName());
finalAccount.setBalance(finalAccount.getBalance().add(BigDecimal.valueOf(amount)));
finalBranch.setBalance(finalBranch.getBalance().add(BigDecimal.valueOf(amount)));
accountRepository.save(finalAccount);
branchRepository.save(finalBranch);
status.releaseSavepoint(savepoint);
return null; });
}
Also failed:
JpaDialect does not support savepoints — check your JPA provider’s capabilities
Then I start to search ‘How to use savepoint in Hibernate’ online:
Please note that this is not a recommended way to use Spring JPA. It’s better to structure your transactions so that you don’t need to use savepoints or nested transactions. If you find yourself needing them, it might be a sign that your transactions are too complex and should be broken down into smaller parts.
Maybe I’m wrong from the beginning, indeed, I won’t encounter it in real application scenarios, but I’m just trying to figure out how to implement it, so let me know if you have any good ideas.
...
🔧 Try To Use `savepoint` In Spring JPA/Hibernate
📈 87.37 Punkte
🔧 Programmierung
🔧 Paralelos entre Hibernate, JPA, Ruby e Rails
📈 36.24 Punkte
🔧 Programmierung
🔧 Java Hibernate vs JPA: Quick Review
📈 36.24 Punkte
🔧 Programmierung
🔧 Learn Spring Boot and Spring Data JPA
📈 35.19 Punkte
🔧 Programmierung
🔧 SavePoint best Explanation
📈 30.16 Punkte
🔧 Programmierung
🔧 SAVEPOINT in SQL
📈 30.16 Punkte
🔧 Programmierung
🔧 Advanced Query Techniques in Spring Data JPA
📈 26.86 Punkte
🔧 Programmierung
🔧 Spring Boot 3 JPA + Auth + JWT
📈 26.86 Punkte
🔧 Programmierung