0
# Transaction Management
1
2
Spring ORM provides platform-agnostic transaction management with support for declarative transactions, programmatic transaction control, resource synchronization, and integration with various ORM frameworks. The transaction management infrastructure ensures ACID properties while providing flexibility across different data access technologies.
3
4
## Capabilities
5
6
### Platform Transaction Management
7
8
Core transaction management abstraction that provides consistent transaction semantics across different ORM frameworks and data access technologies.
9
10
```java { .api }
11
public abstract class AbstractPlatformTransactionManager implements PlatformTransactionManager, Serializable {
12
public final TransactionStatus getTransaction(TransactionDefinition definition) throws TransactionException;
13
public final void commit(TransactionStatus status) throws TransactionException;
14
public final void rollback(TransactionStatus status) throws TransactionException;
15
16
// Template methods for subclass implementation
17
protected abstract Object doGetTransaction() throws TransactionException;
18
protected abstract void doBegin(Object transaction, TransactionDefinition definition) throws TransactionException;
19
protected abstract void doCommit(DefaultTransactionStatus status) throws TransactionException;
20
protected abstract void doRollback(DefaultTransactionStatus status) throws TransactionException;
21
22
// Configuration methods
23
public void setTransactionSynchronization(int transactionSynchronization);
24
public void setDefaultTimeout(int defaultTimeout);
25
public void setNestedTransactionAllowed(boolean nestedTransactionAllowed);
26
public void setValidateExistingTransaction(boolean validateExistingTransaction);
27
public void setGlobalRollbackOnParticipationFailure(boolean globalRollbackOnParticipationFailure);
28
public void setFailEarlyOnGlobalRollbackOnly(boolean failEarlyOnGlobalRollbackOnly);
29
public void setRollbackOnCommitFailure(boolean rollbackOnCommitFailure);
30
}
31
32
public interface ResourceTransactionManager extends PlatformTransactionManager {
33
Object getResourceFactory();
34
}
35
```
36
37
#### Usage Example
38
39
```java
40
@Configuration
41
@EnableTransactionManagement
42
public class TransactionConfig {
43
44
@Bean
45
public PlatformTransactionManager transactionManager(EntityManagerFactory entityManagerFactory) {
46
JpaTransactionManager txManager = new JpaTransactionManager(entityManagerFactory);
47
48
// Configure transaction manager behavior
49
txManager.setDefaultTimeout(30); // 30 seconds default timeout
50
txManager.setNestedTransactionAllowed(true);
51
txManager.setValidateExistingTransaction(true);
52
txManager.setGlobalRollbackOnParticipationFailure(true);
53
54
return txManager;
55
}
56
}
57
58
@Service
59
@Transactional
60
public class BusinessService {
61
62
@Autowired
63
private PlatformTransactionManager transactionManager;
64
65
// Declarative transaction management
66
@Transactional(timeout = 60, rollbackFor = Exception.class)
67
public void performComplexOperation() {
68
// Business logic automatically runs in transaction
69
}
70
71
// Programmatic transaction management
72
public void performProgrammaticTransaction() {
73
TransactionDefinition def = new DefaultTransactionDefinition();
74
TransactionStatus status = transactionManager.getTransaction(def);
75
76
try {
77
// Perform business operations
78
doBusinessLogic();
79
transactionManager.commit(status);
80
} catch (Exception ex) {
81
transactionManager.rollback(status);
82
throw ex;
83
}
84
}
85
}
86
```
87
88
### JPA Transaction Management
89
90
Specialized transaction manager for JPA that manages EntityManager lifecycle, resource synchronization, and JPA-specific transaction semantics.
91
92
```java { .api }
93
public class JpaTransactionManager extends AbstractPlatformTransactionManager
94
implements ResourceTransactionManager, BeanFactoryAware, InitializingBean {
95
public JpaTransactionManager();
96
public JpaTransactionManager(EntityManagerFactory emf);
97
98
public void setEntityManagerFactory(EntityManagerFactory emf);
99
public EntityManagerFactory getEntityManagerFactory();
100
public void setPersistenceUnitName(String persistenceUnitName);
101
public void setJpaProperties(Properties jpaProperties);
102
public void setDataSource(DataSource dataSource);
103
public void setJpaDialect(JpaDialect jpaDialect);
104
public void setEntityManagerInitializer(Consumer<EntityManager> entityManagerInitializer);
105
106
// ResourceTransactionManager implementation
107
public Object getResourceFactory();
108
}
109
```
110
111
#### Usage Example
112
113
```java
114
@Configuration
115
@EnableTransactionManagement
116
@EnableJpaRepositories(basePackages = "com.example.repository")
117
public class JpaTransactionConfig {
118
119
@Bean
120
public JpaTransactionManager transactionManager(EntityManagerFactory entityManagerFactory) {
121
JpaTransactionManager txManager = new JpaTransactionManager();
122
txManager.setEntityManagerFactory(entityManagerFactory);
123
124
// Optional: Set DataSource for connection-level synchronization
125
txManager.setDataSource(dataSource());
126
127
// Optional: Configure JPA-specific properties
128
Properties jpaProperties = new Properties();
129
jpaProperties.setProperty("javax.persistence.lock.timeout", "5000");
130
txManager.setJpaProperties(jpaProperties);
131
132
// Optional: Set custom JPA dialect
133
txManager.setJpaDialect(new HibernateJpaDialect());
134
135
// Optional: Custom EntityManager initialization
136
txManager.setEntityManagerInitializer(em -> {
137
em.setProperty("org.hibernate.readOnly", true);
138
});
139
140
return txManager;
141
}
142
143
@Bean
144
public DataSource dataSource() {
145
HikariDataSource dataSource = new HikariDataSource();
146
dataSource.setJdbcUrl("jdbc:postgresql://localhost:5432/mydb");
147
dataSource.setUsername("user");
148
dataSource.setPassword("password");
149
return dataSource;
150
}
151
}
152
153
@Service
154
@Transactional
155
public class UserService {
156
157
@PersistenceContext
158
private EntityManager entityManager;
159
160
@Transactional(propagation = Propagation.REQUIRED)
161
public void createUser(User user) {
162
entityManager.persist(user);
163
// Transaction commits automatically
164
}
165
166
@Transactional(propagation = Propagation.REQUIRES_NEW)
167
public void logAuditEvent(String action, String details) {
168
AuditEvent event = new AuditEvent();
169
event.setAction(action);
170
event.setDetails(details);
171
event.setTimestamp(Instant.now());
172
entityManager.persist(event);
173
// Runs in separate transaction
174
}
175
176
@Transactional(readOnly = true, timeout = 30)
177
public List<User> findActiveUsers() {
178
return entityManager.createQuery(
179
"SELECT u FROM User u WHERE u.active = true",
180
User.class
181
).getResultList();
182
}
183
}
184
```
185
186
### Hibernate Transaction Management
187
188
Specialized transaction manager for Hibernate that manages Session lifecycle, resource synchronization, and Hibernate-specific transaction semantics.
189
190
```java { .api }
191
public class HibernateTransactionManager extends AbstractPlatformTransactionManager
192
implements ResourceTransactionManager, BeanFactoryAware, InitializingBean {
193
public HibernateTransactionManager();
194
public HibernateTransactionManager(SessionFactory sessionFactory);
195
196
public void setSessionFactory(SessionFactory sessionFactory);
197
public SessionFactory getSessionFactory();
198
public void setDataSource(DataSource dataSource);
199
public void setHibernateProperties(Properties hibernateProperties);
200
public void setEntityInterceptor(Interceptor entityInterceptor);
201
public void setJtaTimeout(int jtaTimeout);
202
203
// ResourceTransactionManager implementation
204
public Object getResourceFactory();
205
}
206
```
207
208
#### Usage Example
209
210
```java
211
@Configuration
212
@EnableTransactionManagement
213
public class HibernateTransactionConfig {
214
215
@Bean
216
public HibernateTransactionManager transactionManager(SessionFactory sessionFactory) {
217
HibernateTransactionManager txManager = new HibernateTransactionManager();
218
txManager.setSessionFactory(sessionFactory);
219
220
// Optional: Set DataSource for connection-level synchronization
221
txManager.setDataSource(dataSource());
222
223
// Optional: Configure Hibernate-specific properties for transactions
224
Properties hibernateProperties = new Properties();
225
hibernateProperties.setProperty("hibernate.connection.isolation", "2"); // READ_COMMITTED
226
hibernateProperties.setProperty("hibernate.jdbc.batch_size", "25");
227
txManager.setHibernateProperties(hibernateProperties);
228
229
// Optional: Set entity interceptor for transaction-scoped sessions
230
txManager.setEntityInterceptor(new AuditInterceptor());
231
232
return txManager;
233
}
234
}
235
236
@Service
237
@Transactional
238
public class ProductService {
239
240
@Autowired
241
private SessionFactory sessionFactory;
242
243
@Transactional(isolation = Isolation.READ_COMMITTED)
244
public void updateProductInventory(Long productId, int quantity) {
245
Session session = sessionFactory.getCurrentSession();
246
247
Product product = session.get(Product.class, productId, LockMode.PESSIMISTIC_WRITE);
248
if (product != null) {
249
product.setInventoryCount(product.getInventoryCount() + quantity);
250
session.update(product);
251
}
252
}
253
254
@Transactional(propagation = Propagation.NESTED)
255
public void processOrderItems(List<OrderItem> items) {
256
Session session = sessionFactory.getCurrentSession();
257
258
for (OrderItem item : items) {
259
try {
260
updateProductInventory(item.getProductId(), -item.getQuantity());
261
session.save(item);
262
} catch (Exception ex) {
263
// Nested transaction can rollback independently
264
log.warn("Failed to process item: " + item.getProductId(), ex);
265
throw ex;
266
}
267
}
268
}
269
}
270
```
271
272
### Transaction Synchronization
273
274
Infrastructure for registering callbacks that participate in Spring transaction lifecycle, enabling custom resource management and cleanup.
275
276
```java { .api }
277
public interface TransactionSynchronization {
278
int STATUS_COMMITTED = 0;
279
int STATUS_ROLLED_BACK = 1;
280
int STATUS_UNKNOWN = 2;
281
282
default void suspend();
283
default void resume();
284
default void flush();
285
default void beforeCommit(boolean readOnly);
286
default void beforeCompletion();
287
default void afterCommit();
288
default void afterCompletion(int status);
289
}
290
291
public abstract class TransactionSynchronizationManager {
292
public static Map<Object, Object> getResourceMap();
293
public static boolean hasResource(Object key);
294
public static Object getResource(Object key);
295
public static void bindResource(Object key, Object value) throws IllegalStateException;
296
public static Object unbindResource(Object key) throws IllegalStateException;
297
public static Object unbindResourceIfPossible(Object key);
298
299
public static boolean isSynchronizationActive();
300
public static void initSynchronization() throws IllegalStateException;
301
public static void registerSynchronization(TransactionSynchronization synchronization) throws IllegalStateException;
302
public static List<TransactionSynchronization> getSynchronizations() throws IllegalStateException;
303
public static void clearSynchronization() throws IllegalStateException;
304
305
public static void setCurrentTransactionName(String name);
306
public static String getCurrentTransactionName();
307
public static void setCurrentTransactionReadOnly(boolean readOnly);
308
public static boolean isCurrentTransactionReadOnly();
309
public static void setCurrentTransactionIsolationLevel(Integer isolationLevel);
310
public static Integer getCurrentTransactionIsolationLevel();
311
public static void setActualTransactionActive(boolean active);
312
public static boolean isActualTransactionActive();
313
}
314
```
315
316
#### Usage Example
317
318
```java
319
@Component
320
public class CustomResourceManager {
321
322
private static final Object RESOURCE_KEY = new Object();
323
324
@EventListener
325
public void handleTransactionBegin(TransactionBeginEvent event) {
326
if (TransactionSynchronizationManager.isSynchronizationActive()) {
327
// Register custom synchronization
328
TransactionSynchronizationManager.registerSynchronization(
329
new CustomTransactionSynchronization()
330
);
331
332
// Bind custom resource to transaction
333
CustomResource resource = new CustomResource();
334
TransactionSynchronizationManager.bindResource(RESOURCE_KEY, resource);
335
}
336
}
337
338
private static class CustomTransactionSynchronization implements TransactionSynchronization {
339
340
@Override
341
public void beforeCommit(boolean readOnly) {
342
if (!readOnly) {
343
CustomResource resource = (CustomResource)
344
TransactionSynchronizationManager.getResource(RESOURCE_KEY);
345
if (resource != null) {
346
resource.prepareForCommit();
347
}
348
}
349
}
350
351
@Override
352
public void afterCommit() {
353
CustomResource resource = (CustomResource)
354
TransactionSynchronizationManager.getResource(RESOURCE_KEY);
355
if (resource != null) {
356
resource.afterCommit();
357
}
358
}
359
360
@Override
361
public void afterCompletion(int status) {
362
try {
363
CustomResource resource = (CustomResource)
364
TransactionSynchronizationManager.unbindResourceIfPossible(RESOURCE_KEY);
365
if (resource != null) {
366
if (status == STATUS_COMMITTED) {
367
resource.cleanup();
368
} else {
369
resource.rollback();
370
}
371
}
372
} finally {
373
// Ensure cleanup happens regardless
374
}
375
}
376
}
377
}
378
```
379
380
### Declarative Transaction Configuration
381
382
Annotation-driven transaction management configuration with support for customization and various transaction managers.
383
384
```java { .api }
385
@Target(ElementType.TYPE)
386
@Retention(RetentionPolicy.RUNTIME)
387
@Documented
388
@Import(TransactionManagementConfigurationSelector.class)
389
public @interface EnableTransactionManagement {
390
boolean proxyTargetClass() default false;
391
AdviceMode mode() default AdviceMode.PROXY;
392
int order() default Ordered.LOWEST_PRECEDENCE;
393
}
394
395
@Target({ElementType.TYPE, ElementType.METHOD})
396
@Retention(RetentionPolicy.RUNTIME)
397
@Inherited
398
@Documented
399
public @interface Transactional {
400
String value() default "";
401
String transactionManager() default "";
402
Propagation propagation() default Propagation.REQUIRED;
403
Isolation isolation() default Isolation.DEFAULT;
404
int timeout() default TransactionDefinition.TIMEOUT_DEFAULT;
405
boolean readOnly() default false;
406
Class<? extends Throwable>[] rollbackFor() default {};
407
String[] rollbackForClassName() default {};
408
Class<? extends Throwable>[] noRollbackFor() default {};
409
String[] noRollbackForClassName() default {};
410
}
411
412
public enum Propagation {
413
REQUIRED(TransactionDefinition.PROPAGATION_REQUIRED),
414
SUPPORTS(TransactionDefinition.PROPAGATION_SUPPORTS),
415
MANDATORY(TransactionDefinition.PROPAGATION_MANDATORY),
416
REQUIRES_NEW(TransactionDefinition.PROPAGATION_REQUIRES_NEW),
417
NOT_SUPPORTED(TransactionDefinition.PROPAGATION_NOT_SUPPORTED),
418
NEVER(TransactionDefinition.PROPAGATION_NEVER),
419
NESTED(TransactionDefinition.PROPAGATION_NESTED);
420
}
421
422
public enum Isolation {
423
DEFAULT(TransactionDefinition.ISOLATION_DEFAULT),
424
READ_UNCOMMITTED(TransactionDefinition.ISOLATION_READ_UNCOMMITTED),
425
READ_COMMITTED(TransactionDefinition.ISOLATION_READ_COMMITTED),
426
REPEATABLE_READ(TransactionDefinition.ISOLATION_REPEATABLE_READ),
427
SERIALIZABLE(TransactionDefinition.ISOLATION_SERIALIZABLE);
428
}
429
```
430
431
#### Usage Example
432
433
```java
434
@Configuration
435
@EnableTransactionManagement(
436
proxyTargetClass = true, // Use CGLIB proxies
437
mode = AdviceMode.PROXY, // Use proxy-based AOP
438
order = Ordered.LOWEST_PRECEDENCE // Transaction advice order
439
)
440
public class TransactionManagementConfig {
441
442
@Bean
443
public TransactionAttributeSource transactionAttributeSource() {
444
AnnotationTransactionAttributeSource source = new AnnotationTransactionAttributeSource();
445
return source;
446
}
447
448
@Bean
449
public TransactionInterceptor transactionInterceptor(
450
PlatformTransactionManager transactionManager,
451
TransactionAttributeSource transactionAttributeSource) {
452
TransactionInterceptor interceptor = new TransactionInterceptor();
453
interceptor.setTransactionManager(transactionManager);
454
interceptor.setTransactionAttributeSource(transactionAttributeSource);
455
return interceptor;
456
}
457
}
458
459
@Service
460
public class OrderService {
461
462
// Method-level transaction with specific settings
463
@Transactional(
464
propagation = Propagation.REQUIRED,
465
isolation = Isolation.READ_COMMITTED,
466
timeout = 30,
467
rollbackFor = {BusinessException.class, DataIntegrityViolationException.class},
468
noRollbackFor = {ValidationException.class}
469
)
470
public void processOrder(Order order) {
471
validateOrder(order);
472
saveOrder(order);
473
updateInventory(order.getItems());
474
sendNotification(order);
475
}
476
477
// Read-only transaction for queries
478
@Transactional(readOnly = true, timeout = 15)
479
public List<Order> findOrdersByCustomer(Long customerId) {
480
return orderRepository.findByCustomerId(customerId);
481
}
482
483
// Requires new transaction (always runs in separate transaction)
484
@Transactional(propagation = Propagation.REQUIRES_NEW)
485
public void auditOrderOperation(String operation, Long orderId) {
486
AuditLog log = new AuditLog();
487
log.setOperation(operation);
488
log.setEntityId(orderId);
489
log.setTimestamp(Instant.now());
490
auditRepository.save(log);
491
}
492
}
493
494
// Class-level transaction settings (inherited by all methods)
495
@Service
496
@Transactional(
497
transactionManager = "orderTransactionManager", // Specific transaction manager
498
propagation = Propagation.REQUIRED,
499
isolation = Isolation.READ_COMMITTED,
500
timeout = 30
501
)
502
public class InventoryService {
503
504
// Inherits class-level transaction settings
505
public void updateStock(Long productId, int quantity) {
506
// Business logic
507
}
508
509
// Override class-level settings for this method
510
@Transactional(
511
propagation = Propagation.REQUIRES_NEW,
512
isolation = Isolation.SERIALIZABLE
513
)
514
public void criticalStockUpdate(Long productId, int quantity) {
515
// Critical business logic requiring separate transaction
516
}
517
518
// Non-transactional method
519
@Transactional(propagation = Propagation.NOT_SUPPORTED)
520
public void generateReport() {
521
// Report generation doesn't need transaction
522
}
523
}
524
```
525
526
### Transaction Definition and Status
527
528
Core interfaces and classes that define transaction characteristics and provide runtime transaction information.
529
530
```java { .api }
531
public interface TransactionDefinition {
532
int PROPAGATION_REQUIRED = 0;
533
int PROPAGATION_SUPPORTS = 1;
534
int PROPAGATION_MANDATORY = 2;
535
int PROPAGATION_REQUIRES_NEW = 3;
536
int PROPAGATION_NOT_SUPPORTED = 4;
537
int PROPAGATION_NEVER = 5;
538
int PROPAGATION_NESTED = 6;
539
540
int ISOLATION_DEFAULT = -1;
541
int ISOLATION_READ_UNCOMMITTED = 1;
542
int ISOLATION_READ_COMMITTED = 2;
543
int ISOLATION_REPEATABLE_READ = 4;
544
int ISOLATION_SERIALIZABLE = 8;
545
546
int TIMEOUT_DEFAULT = -1;
547
548
default int getPropagationBehavior();
549
default int getIsolationLevel();
550
default int getTimeout();
551
default boolean isReadOnly();
552
default String getName();
553
}
554
555
public class DefaultTransactionDefinition implements TransactionDefinition, Serializable {
556
public DefaultTransactionDefinition();
557
public DefaultTransactionDefinition(TransactionDefinition other);
558
public DefaultTransactionDefinition(int propagationBehavior);
559
560
public void setPropagationBehavior(int propagationBehavior);
561
public void setIsolationLevel(int isolationLevel);
562
public void setTimeout(int timeout);
563
public void setReadOnly(boolean readOnly);
564
public void setName(String name);
565
}
566
567
public interface TransactionStatus extends TransactionExecution, SavepointManager, Flushable {
568
boolean hasSavepoint();
569
void flush();
570
}
571
572
public interface TransactionExecution {
573
boolean isNewTransaction();
574
void setRollbackOnly();
575
boolean isRollbackOnly();
576
boolean isCompleted();
577
}
578
```
579
580
#### Usage Example
581
582
```java
583
@Service
584
public class PaymentService {
585
586
@Autowired
587
private PlatformTransactionManager transactionManager;
588
589
public void processPaymentWithCustomTransaction(Payment payment) {
590
// Create custom transaction definition
591
DefaultTransactionDefinition def = new DefaultTransactionDefinition();
592
def.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);
593
def.setIsolationLevel(TransactionDefinition.ISOLATION_SERIALIZABLE);
594
def.setTimeout(60); // 60 second timeout
595
def.setReadOnly(false);
596
def.setName("PaymentProcessing");
597
598
TransactionStatus status = transactionManager.getTransaction(def);
599
600
try {
601
// Validate payment
602
validatePayment(payment);
603
604
// Process payment
605
processPaymentInternal(payment);
606
607
// Check transaction status
608
if (!status.isRollbackOnly()) {
609
// Create savepoint for partial rollback capability
610
Object savepoint = status.createSavepoint();
611
612
try {
613
// Additional processing that might fail
614
sendPaymentNotification(payment);
615
} catch (Exception ex) {
616
// Rollback to savepoint
617
status.rollbackToSavepoint(savepoint);
618
log.warn("Notification failed, but payment processed", ex);
619
}
620
}
621
622
transactionManager.commit(status);
623
624
} catch (Exception ex) {
625
if (!status.isCompleted()) {
626
transactionManager.rollback(status);
627
}
628
throw new PaymentProcessingException("Payment processing failed", ex);
629
}
630
}
631
}
632
```
633
634
## Types
635
636
```java { .api }
637
import org.springframework.transaction.PlatformTransactionManager;
638
import org.springframework.transaction.TransactionDefinition;
639
import org.springframework.transaction.TransactionStatus;
640
import org.springframework.transaction.TransactionException;
641
import org.springframework.transaction.annotation.Transactional;
642
import org.springframework.transaction.annotation.EnableTransactionManagement;
643
import org.springframework.transaction.annotation.Propagation;
644
import org.springframework.transaction.annotation.Isolation;
645
import org.springframework.transaction.support.TransactionSynchronization;
646
import org.springframework.transaction.support.TransactionSynchronizationManager;
647
import org.springframework.transaction.support.DefaultTransactionDefinition;
648
import org.springframework.transaction.support.DefaultTransactionStatus;
649
import org.springframework.transaction.interceptor.TransactionInterceptor;
650
import org.springframework.transaction.interceptor.TransactionAttributeSource;
651
import org.springframework.orm.jpa.JpaTransactionManager;
652
import org.springframework.orm.hibernate5.HibernateTransactionManager;
653
import jakarta.persistence.EntityManagerFactory;
654
import org.hibernate.SessionFactory;
655
import javax.sql.DataSource;
656
import java.util.Properties;
657
import java.util.function.Consumer;
658
import java.util.Map;
659
import java.util.List;
660
```