or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

core-transaction-management.mddao-exceptions.mddeclarative-transactions.mdindex.mdjta-integration.mdprogrammatic-transactions.mdreactive-transactions.mdtransaction-synchronization.mdtransactional-events.md

declarative-transactions.mddocs/

0

# Declarative Transaction Management

1

2

Spring's declarative transaction management enables transaction control through annotations and configuration, providing clean separation between business logic and transaction concerns using Aspect-Oriented Programming (AOP).

3

4

## Core Annotations

5

6

### @Transactional

7

8

The primary annotation for declarative transaction demarcation, applicable to classes and methods.

9

10

```java { .api }

11

@Target({ElementType.TYPE, ElementType.METHOD})

12

@Retention(RetentionPolicy.RUNTIME)

13

@Documented

14

public @interface Transactional {

15

/**

16

* Alias for transactionManager.

17

* @return the transaction manager bean name

18

*/

19

@AliasFor("transactionManager")

20

String value() default "";

21

22

/**

23

* Specify the transaction manager to use.

24

* @return the transaction manager bean name

25

*/

26

@AliasFor("value")

27

String transactionManager() default "";

28

29

/**

30

* Define transaction propagation behavior.

31

* @return the propagation behavior

32

*/

33

Propagation propagation() default Propagation.REQUIRED;

34

35

/**

36

* Define transaction isolation level.

37

* @return the isolation level

38

*/

39

Isolation isolation() default Isolation.DEFAULT;

40

41

/**

42

* Define transaction timeout in seconds.

43

* @return the timeout in seconds

44

*/

45

int timeout() default TransactionDefinition.TIMEOUT_DEFAULT;

46

47

/**

48

* Define whether transaction is read-only.

49

* @return true if read-only

50

*/

51

boolean readOnly() default false;

52

53

/**

54

* Define exception types that trigger rollback.

55

* @return exception classes for rollback

56

*/

57

Class<? extends Throwable>[] rollbackFor() default {};

58

59

/**

60

* Define exception class names that trigger rollback.

61

* @return exception class names for rollback

62

*/

63

String[] rollbackForClassName() default {};

64

65

/**

66

* Define exception types that do NOT trigger rollback.

67

* @return exception classes to not rollback for

68

*/

69

Class<? extends Throwable>[] noRollbackFor() default {};

70

71

/**

72

* Define exception class names that do NOT trigger rollback.

73

* @return exception class names to not rollback for

74

*/

75

String[] noRollbackForClassName() default {};

76

}

77

```

78

79

### @EnableTransactionManagement

80

81

Configuration annotation to enable annotation-driven transaction management.

82

83

```java { .api }

84

@Target(ElementType.TYPE)

85

@Retention(RetentionPolicy.RUNTIME)

86

@Documented

87

@Import(TransactionManagementConfigurationSelector.class)

88

public @interface EnableTransactionManagement {

89

/**

90

* Indicate whether subclass-based (CGLIB) proxies should be created.

91

* @return true for CGLIB proxies, false for JDK dynamic proxies

92

*/

93

boolean proxyTargetClass() default false;

94

95

/**

96

* Indicate how transactional advice should be applied.

97

* @return advice mode (PROXY or ASPECTJ)

98

*/

99

AdviceMode mode() default AdviceMode.PROXY;

100

101

/**

102

* Indicate the order in which the TransactionInterceptor should be applied.

103

* @return the order value

104

*/

105

int order() default Ordered.LOWEST_PRECEDENCE;

106

}

107

108

public enum AdviceMode {

109

PROXY, ASPECTJ

110

}

111

```

112

113

## Propagation and Isolation Enums

114

115

### Propagation

116

117

Enumeration for transaction propagation behaviors corresponding to TransactionDefinition constants.

118

119

```java { .api }

120

public enum Propagation {

121

/**

122

* Support a current transaction; create a new one if none exists.

123

*/

124

REQUIRED(TransactionDefinition.PROPAGATION_REQUIRED),

125

126

/**

127

* Support a current transaction; execute non-transactionally if none exists.

128

*/

129

SUPPORTS(TransactionDefinition.PROPAGATION_SUPPORTS),

130

131

/**

132

* Support a current transaction; throw an exception if no current transaction exists.

133

*/

134

MANDATORY(TransactionDefinition.PROPAGATION_MANDATORY),

135

136

/**

137

* Create a new transaction, suspending the current transaction if one exists.

138

*/

139

REQUIRES_NEW(TransactionDefinition.PROPAGATION_REQUIRES_NEW),

140

141

/**

142

* Do not support a current transaction; rather always execute non-transactionally.

143

*/

144

NOT_SUPPORTED(TransactionDefinition.PROPAGATION_NOT_SUPPORTED),

145

146

/**

147

* Do not support a current transaction; throw an exception if a current transaction exists.

148

*/

149

NEVER(TransactionDefinition.PROPAGATION_NEVER),

150

151

/**

152

* Execute within a nested transaction if a current transaction exists.

153

*/

154

NESTED(TransactionDefinition.PROPAGATION_NESTED);

155

156

private final int value;

157

158

Propagation(int value) {

159

this.value = value;

160

}

161

162

public int value() {

163

return this.value;

164

}

165

}

166

```

167

168

### Isolation

169

170

Enumeration for transaction isolation levels corresponding to TransactionDefinition constants.

171

172

```java { .api }

173

public enum Isolation {

174

/**

175

* Use the default isolation level of the underlying datastore.

176

*/

177

DEFAULT(TransactionDefinition.ISOLATION_DEFAULT),

178

179

/**

180

* Dirty reads, non-repeatable reads, and phantom reads can occur.

181

*/

182

READ_UNCOMMITTED(TransactionDefinition.ISOLATION_READ_UNCOMMITTED),

183

184

/**

185

* Dirty reads are prevented; non-repeatable reads and phantom reads can occur.

186

*/

187

READ_COMMITTED(TransactionDefinition.ISOLATION_READ_COMMITTED),

188

189

/**

190

* Dirty reads and non-repeatable reads are prevented; phantom reads can occur.

191

*/

192

REPEATABLE_READ(TransactionDefinition.ISOLATION_REPEATABLE_READ),

193

194

/**

195

* Dirty reads, non-repeatable reads, and phantom reads are prevented.

196

*/

197

SERIALIZABLE(TransactionDefinition.ISOLATION_SERIALIZABLE);

198

199

private final int value;

200

201

Isolation(int value) {

202

this.value = value;

203

}

204

205

public int value() {

206

return this.value;

207

}

208

}

209

```

210

211

## Configuration Classes

212

213

### TransactionManagementConfigurer

214

215

Interface for transaction management configuration customization.

216

217

```java { .api }

218

public interface TransactionManagementConfigurer {

219

/**

220

* Return the default transaction manager bean to use for annotation-driven database

221

* transaction management.

222

* @return the default transaction manager, or null if there is no single default

223

*/

224

@Nullable

225

PlatformTransactionManager annotationDrivenTransactionManager();

226

}

227

```

228

229

### ProxyTransactionManagementConfiguration

230

231

Configuration class for proxy-based transaction management.

232

233

```java { .api }

234

@Configuration

235

@Role(BeanDefinition.ROLE_INFRASTRUCTURE)

236

public class ProxyTransactionManagementConfiguration extends AbstractTransactionManagementConfiguration {

237

238

@Bean(name = TransactionManagementConfigUtils.TRANSACTION_ADVISOR_BEAN_NAME)

239

@Role(BeanDefinition.ROLE_INFRASTRUCTURE)

240

public BeanFactoryTransactionAttributeSourceAdvisor transactionAdvisor(

241

TransactionAttributeSource transactionAttributeSource,

242

TransactionInterceptor transactionInterceptor);

243

244

@Bean

245

@Role(BeanDefinition.ROLE_INFRASTRUCTURE)

246

public TransactionAttributeSource transactionAttributeSource();

247

248

@Bean

249

@Role(BeanDefinition.ROLE_INFRASTRUCTURE)

250

public TransactionInterceptor transactionInterceptor(

251

TransactionAttributeSource transactionAttributeSource);

252

}

253

```

254

255

## Transaction Attributes

256

257

### TransactionAttribute

258

259

Extended transaction definition interface for interceptor-based transactions.

260

261

```java { .api }

262

public interface TransactionAttribute extends TransactionDefinition {

263

/**

264

* Return a qualifier value associated with this transaction attribute.

265

* @return qualifier value, or null if none

266

*/

267

@Nullable

268

String getQualifier();

269

270

/**

271

* Return descriptive labels associated with this transaction attribute.

272

* @return label array, or null if none

273

*/

274

@Nullable

275

String[] getLabels();

276

277

/**

278

* Should we roll back on the given exception?

279

* @param ex the exception to evaluate

280

* @return whether to perform a rollback or not

281

*/

282

boolean rollbackOn(Throwable ex);

283

}

284

```

285

286

### RuleBasedTransactionAttribute

287

288

Rule-based transaction attribute implementation that handles rollback rules.

289

290

```java { .api }

291

public class RuleBasedTransactionAttribute extends DefaultTransactionAttribute implements Serializable {

292

293

public RuleBasedTransactionAttribute();

294

public RuleBasedTransactionAttribute(RuleBasedTransactionAttribute other);

295

public RuleBasedTransactionAttribute(int propagationBehavior, List<RollbackRuleAttribute> rollbackRules);

296

297

public void setRollbackRules(List<RollbackRuleAttribute> rollbackRules);

298

public List<RollbackRuleAttribute> getRollbackRules();

299

300

@Override

301

public boolean rollbackOn(Throwable ex);

302

}

303

```

304

305

### RollbackRuleAttribute

306

307

Rule for determining rollback behavior based on exception types.

308

309

```java { .api }

310

public class RollbackRuleAttribute implements Serializable {

311

public static final RollbackRuleAttribute ROLLBACK_ON_RUNTIME_EXCEPTIONS =

312

new RollbackRuleAttribute(RuntimeException.class);

313

314

public RollbackRuleAttribute(Class<?> clazz);

315

public RollbackRuleAttribute(String exceptionName);

316

317

public int getDepth(Throwable ex);

318

public Class<?> getExceptionType();

319

public String getExceptionName();

320

}

321

322

public class NoRollbackRuleAttribute extends RollbackRuleAttribute {

323

public NoRollbackRuleAttribute(Class<?> clazz);

324

public NoRollbackRuleAttribute(String exceptionName);

325

}

326

```

327

328

## Transaction Attribute Sources

329

330

### AnnotationTransactionAttributeSource

331

332

Transaction attribute source that reads transaction attributes from annotations.

333

334

```java { .api }

335

public class AnnotationTransactionAttributeSource extends AbstractFallbackTransactionAttributeSource

336

implements Serializable {

337

338

public AnnotationTransactionAttributeSource();

339

public AnnotationTransactionAttributeSource(boolean publicMethodsOnly);

340

public AnnotationTransactionAttributeSource(TransactionAnnotationParser... annotationParsers);

341

public AnnotationTransactionAttributeSource(Set<TransactionAnnotationParser> annotationParsers);

342

343

public void setAnnotationParsers(Set<TransactionAnnotationParser> annotationParsers);

344

public void setPublicMethodsOnly(boolean publicMethodsOnly);

345

346

@Override

347

@Nullable

348

protected TransactionAttribute findTransactionAttribute(Class<?> clazz);

349

350

@Override

351

@Nullable

352

protected TransactionAttribute findTransactionAttribute(Method method);

353

}

354

```

355

356

### CompositeTransactionAttributeSource

357

358

Composite transaction attribute source that delegates to multiple sources.

359

360

```java { .api }

361

public class CompositeTransactionAttributeSource implements TransactionAttributeSource, Serializable {

362

363

public CompositeTransactionAttributeSource(TransactionAttributeSource... transactionAttributeSources);

364

365

@Override

366

@Nullable

367

public TransactionAttribute getTransactionAttribute(Method method, @Nullable Class<?> targetClass);

368

}

369

```

370

371

## Usage Examples

372

373

### Basic Declarative Transactions

374

375

```java

376

@Service

377

@Transactional

378

public class UserService {

379

380

private final UserRepository userRepository;

381

private final EmailService emailService;

382

383

public UserService(UserRepository userRepository, EmailService emailService) {

384

this.userRepository = userRepository;

385

this.emailService = emailService;

386

}

387

388

// Read-only transaction for queries

389

@Transactional(readOnly = true)

390

public User findUser(Long id) {

391

return userRepository.findById(id)

392

.orElseThrow(() -> new UserNotFoundException(id));

393

}

394

395

// Default transaction settings (REQUIRED propagation, READ_COMMITTED isolation)

396

public User createUser(User user) {

397

User savedUser = userRepository.save(user);

398

emailService.sendWelcomeEmail(savedUser);

399

return savedUser;

400

}

401

402

// Custom isolation level and rollback rules

403

@Transactional(

404

isolation = Isolation.SERIALIZABLE,

405

rollbackFor = {DataIntegrityViolationException.class, ValidationException.class},

406

timeout = 10

407

)

408

public User updateUserEmail(Long userId, String newEmail) {

409

User user = userRepository.findById(userId)

410

.orElseThrow(() -> new UserNotFoundException(userId));

411

412

// Check if email already exists

413

if (userRepository.existsByEmail(newEmail)) {

414

throw new ValidationException("Email already in use");

415

}

416

417

user.setEmail(newEmail);

418

return userRepository.save(user);

419

}

420

}

421

```

422

423

### Transaction Propagation Examples

424

425

```java

426

@Service

427

@Transactional

428

public class OrderService {

429

430

private final OrderRepository orderRepository;

431

private final InventoryService inventoryService;

432

private final PaymentService paymentService;

433

private final AuditService auditService;

434

435

// REQUIRED: Join existing transaction or create new one

436

@Transactional(propagation = Propagation.REQUIRED)

437

public Order processOrder(Order order) {

438

Order savedOrder = orderRepository.save(order);

439

inventoryService.reserveItems(order.getItems()); // Joins this transaction

440

paymentService.processPayment(order.getPayment()); // Joins this transaction

441

return savedOrder;

442

}

443

444

// REQUIRES_NEW: Always create new transaction, suspend existing

445

@Transactional(propagation = Propagation.REQUIRES_NEW)

446

public void logOrderAttempt(Order order) {

447

// This runs in separate transaction, commits independently

448

auditService.logAttempt("order.process", order.getId());

449

}

450

451

// SUPPORTS: Join transaction if exists, run non-transactionally otherwise

452

@Transactional(propagation = Propagation.SUPPORTS, readOnly = true)

453

public List<Order> findRecentOrders(Long userId) {

454

return orderRepository.findByUserIdAndCreatedAtAfter(

455

userId, LocalDateTime.now().minusDays(30));

456

}

457

458

// MANDATORY: Must have existing transaction, throw exception otherwise

459

@Transactional(propagation = Propagation.MANDATORY)

460

public void updateOrderStatus(Long orderId, OrderStatus status) {

461

Order order = orderRepository.findById(orderId)

462

.orElseThrow(() -> new OrderNotFoundException(orderId));

463

order.setStatus(status);

464

orderRepository.save(order);

465

}

466

467

// NESTED: Create nested transaction with savepoint

468

@Transactional(propagation = Propagation.NESTED)

469

public void processOptionalUpgrade(Order order, Upgrade upgrade) {

470

try {

471

// This runs in nested transaction

472

upgradeService.applyUpgrade(order, upgrade);

473

} catch (UpgradeException e) {

474

// Nested transaction rolls back, main transaction continues

475

log.warn("Upgrade failed for order {}, continuing without upgrade", order.getId());

476

}

477

}

478

}

479

```

480

481

### Configuration Examples

482

483

```java

484

@Configuration

485

@EnableTransactionManagement

486

public class TransactionConfig {

487

488

@Bean

489

public PlatformTransactionManager transactionManager(DataSource dataSource) {

490

return new DataSourceTransactionManager(dataSource);

491

}

492

}

493

494

// Custom transaction management configuration

495

@Configuration

496

@EnableTransactionManagement

497

public class CustomTransactionConfig implements TransactionManagementConfigurer {

498

499

@Bean

500

@Primary

501

public PlatformTransactionManager primaryTransactionManager(

502

@Qualifier("primaryDataSource") DataSource dataSource) {

503

return new DataSourceTransactionManager(dataSource);

504

}

505

506

@Bean

507

public PlatformTransactionManager secondaryTransactionManager(

508

@Qualifier("secondaryDataSource") DataSource dataSource) {

509

return new DataSourceTransactionManager(dataSource);

510

}

511

512

@Override

513

public PlatformTransactionManager annotationDrivenTransactionManager() {

514

return primaryTransactionManager(null); // Return primary by default

515

}

516

}

517

518

// Service using multiple transaction managers

519

@Service

520

public class MultiDataSourceService {

521

522

@Transactional("primaryTransactionManager")

523

public void saveToPrimary(Entity entity) {

524

primaryRepository.save(entity);

525

}

526

527

@Transactional("secondaryTransactionManager")

528

public void saveToSecondary(Entity entity) {

529

secondaryRepository.save(entity);

530

}

531

532

@Transactional("primaryTransactionManager")

533

public void saveToMultiple(Entity entity) {

534

primaryRepository.save(entity);

535

// This will not participate in the primary transaction

536

saveToSecondaryInNewTransaction(entity);

537

}

538

539

@Transactional(value = "secondaryTransactionManager", propagation = Propagation.REQUIRES_NEW)

540

private void saveToSecondaryInNewTransaction(Entity entity) {

541

secondaryRepository.save(entity);

542

}

543

}

544

```

545

546

### Advanced Rollback Rules

547

548

```java

549

@Service

550

@Transactional

551

public class PaymentService {

552

553

// Rollback for all exceptions except specific business exceptions

554

@Transactional(

555

rollbackFor = Exception.class,

556

noRollbackFor = {InsufficientFundsException.class, PaymentDeclinedException.class}

557

)

558

public PaymentResult processPayment(Payment payment) {

559

try {

560

return paymentGateway.charge(payment);

561

} catch (InsufficientFundsException | PaymentDeclinedException e) {

562

// These don't rollback transaction, log and return failure result

563

log.warn("Payment failed: {}", e.getMessage());

564

return PaymentResult.failed(e.getMessage());

565

}

566

// Other exceptions (network issues, etc.) will rollback transaction

567

}

568

569

// Custom rollback rules using class names

570

@Transactional(

571

rollbackForClassName = {"java.lang.Exception"},

572

noRollbackForClassName = {"com.example.business.BusinessException"}

573

)

574

public void processWithStringRules(ProcessingRequest request) {

575

// Processing logic

576

}

577

}

578

```

579

580

## Class-Level vs Method-Level Annotations

581

582

```java

583

@Service

584

@Transactional(readOnly = true) // Default for all methods

585

public class ReadHeavyService {

586

587

// Inherits class-level @Transactional(readOnly = true)

588

public List<User> findAllUsers() {

589

return userRepository.findAll();

590

}

591

592

// Overrides class-level settings

593

@Transactional(readOnly = false, rollbackFor = Exception.class)

594

public User createUser(User user) {

595

return userRepository.save(user);

596

}

597

598

// Combines with class-level settings (readOnly overridden, other settings inherited)

599

@Transactional(readOnly = false, propagation = Propagation.REQUIRES_NEW)

600

public User updateUserInNewTransaction(User user) {

601

return userRepository.save(user);

602

}

603

}

604

```