1. Introduction
Programmatic transaction management is to manage transactions by writing code, which provides finer granular transaction control over declarative transactions (@Transactional annotation). In SpringBoot, there are two main implementation methods:
- Use TransactionTemplate
- Use TransactionManager directly
2. TransactionTemplate method
TransactionTemplate is the simplest way to implement programming transactions. It encapsulates the underlying transaction API and is more convenient to use.
2.1 Basic configuration
@Configuration public class TransactionConfig { @Autowired private PlatformTransactionManager transactionManager; @Bean public TransactionTemplate transactionTemplate() { TransactionTemplate template = new TransactionTemplate(); (transactionManager); // Set the default transaction propagation behavior (TransactionDefinition.PROPAGATION_REQUIRED); // Set the default transaction isolation level (TransactionDefinition.ISOLATION_DEFAULT); // Set the default timeout (30); return template; } }
2.2 Basic usage examples
@Service @Slf4j public class UserService { @Autowired private TransactionTemplate transactionTemplate; @Autowired private UserRepository userRepository; public User createUser(User user) { // Use the execute method to perform transaction operations with return values return (status -> { try { User savedUser = (user); // Simulate other operations updateUserProfile(savedUser); return savedUser; } catch (Exception e) { // Manually mark transaction rollback (); ("Creating user failed", e); throw new RuntimeException("Creating user failed", e); } }); } public void batchCreateUsers(List<User> users) { // Use the executeWithoutResult method to perform transaction operations without return value (status -> { try { for (User user : users) { (user); } } catch (Exception e) { (); ("Batch creation of user failed", e); throw new RuntimeException("Batch creation of user failed", e); } }); } }
3. TransactionManager method
Directly using TransactionManager provides finer granular transaction control, but is relatively complex to use.
3.1 Basic usage examples
@Service @Slf4j public class OrderService { @Autowired private PlatformTransactionManager transactionManager; @Autowired private OrderRepository orderRepository; public Order createOrder(Order order) { // Define transaction properties DefaultTransactionDefinition def = new DefaultTransactionDefinition(); (TransactionDefinition.PROPAGATION_REQUIRED); (TransactionDefinition.ISOLATION_READ_COMMITTED); (30); // Get transaction status TransactionStatus status = (def); try { // Execute business logic Order savedOrder = (order); // Other operations related to handling orders processOrderDetails(savedOrder); // Submit transaction (status); return savedOrder; } catch (Exception e) { // Roll back the transaction (status); ("Create order failed", e); throw new RuntimeException("Create order failed", e); } } }
3.2 Nested Transaction Example
@Service @Slf4j public class PaymentService { @Autowired private PlatformTransactionManager transactionManager; @Autowired private PaymentRepository paymentRepository; public void processPayment(Payment payment) { // External transaction definition DefaultTransactionDefinition outerDef = new DefaultTransactionDefinition(); (TransactionDefinition.PROPAGATION_REQUIRED); TransactionStatus outerStatus = (outerDef); try { // External transaction operations (payment); // Internal transaction definition DefaultTransactionDefinition innerDef = new DefaultTransactionDefinition(); (TransactionDefinition.PROPAGATION_NESTED); TransactionStatus innerStatus = (innerDef); try { // Perform internal transaction operations processPaymentDetails(payment); (innerStatus); } catch (Exception e) { // Roll back internal transactions (innerStatus); ("Payment details processing failed", e); throw e; } // Submit external transactions (outerStatus); } catch (Exception e) { // Roll back external transactions (outerStatus); ("Payment processing failed", e); throw new RuntimeException("Payment processing failed", e); } } }
4. Transaction communication behavior
In a programming transaction, we can accurately control the propagation behavior of the transaction:
@Service public class TransactionPropagationExample { @Autowired private TransactionTemplate transactionTemplate; public void demonstratePropagation() { // REQUIRED propagation behavior TransactionTemplate requiredTemplate = new TransactionTemplate(transactionTemplate); (TransactionDefinition.PROPAGATION_REQUIRED); // REQUIRES_NEW Propagation Behavior TransactionTemplate requiresNewTemplate = new TransactionTemplate(transactionTemplate); (TransactionDefinition.PROPAGATION_REQUIRES_NEW); //Nesting different propagation behaviors (outerStatus -> { // External transaction logic (innerStatus -> { // Internal transaction logic (new transaction) return null; }); return null; }); } }
5. Transaction isolation level
Examples show how to set different transaction isolation levels:
@Service public class TransactionIsolationExample { @Autowired private PlatformTransactionManager transactionManager; public void demonstrateIsolation() { // Read the submitted isolation level DefaultTransactionDefinition readCommittedDef = new DefaultTransactionDefinition(); (TransactionDefinition.ISOLATION_READ_COMMITTED); TransactionStatus readCommittedStatus = (readCommittedDef); try { // Business logic (readCommittedStatus); } catch (Exception e) { (readCommittedStatus); throw e; } // Repeatable isolation level DefaultTransactionDefinition repeatableReadDef = new DefaultTransactionDefinition(); (TransactionDefinition.ISOLATION_REPEATABLE_READ); // ... Similar transaction processing logic } }
6. Best Practices
6.1 Transaction template encapsulation
Create a common transaction template:
@Component @Slf4j public class TransactionHelper { @Autowired private TransactionTemplate transactionTemplate; public <T> T executeInTransaction(TransactionCallback<T> action) { try { return (action); } catch (Exception e) { ("Transaction execution failed", e); throw new RuntimeException("Transaction execution failed", e); } } public void executeInTransactionWithoutResult(Consumer<TransactionStatus> action) { try { (action); } catch (Exception e) { ("Transaction execution failed", e); throw new RuntimeException("Transaction execution failed", e); } } } // Use example@Service public class BusinessService { @Autowired private TransactionHelper transactionHelper; public void doBusiness() { (status -> { // Business logic }); } }
7. FAQs and Solutions
7.1 Transaction timeout processing
@Service public class TimeoutExample { @Autowired private TransactionTemplate transactionTemplate; public void handleTimeout() { TransactionTemplate timeoutTemplate = new TransactionTemplate(transactionTemplate); (5); // Set 5 seconds timeout try { (status -> { // Business logic that may timeout return null; }); } catch (TransactionTimedOutException e) { // Handle timeout exception ("Transaction execution timeout", e); throw new RuntimeException("Transaction execution timeout", e); } } }
7.2 Exception handling best practices
@Service public class ExceptionHandlingExample { @Autowired private TransactionTemplate transactionTemplate; public void handleExceptions() { try { (status -> { try { // Business logic return null; } catch (BusinessException e) { // Business exception, mark rollback (); throw e; } catch (Exception e) { // Other exceptions, mark rollback (); throw new RuntimeException("Unexpected Error", e); } }); } catch (Exception e) { // Unified exception handling handleException(e); } } private void handleException(Exception e) { if (e instanceof BusinessException) { // Handle business exceptions ("Business exception: {}", ()); } else { // Handle system exceptions ("System Exception", e); } throw e; } }
While programming transactions provide finer granular control, in most cases declarative transactions (@Transactional) may be a better choice. Use of programmatic transactions is only considered when particularly fine transaction control is required.
This is the end of this article about the use of SpringBoot programming transactions. For more related SpringBoot programming transactions, please search for my previous articles or continue browsing the related articles below. I hope everyone will support me in the future!