or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

core-transaction-management.mddatasource-auto-proxying.mdhttp-transaction-propagation.mdindex.mdsaga-pattern-support.md

datasource-auto-proxying.mddocs/

0

# DataSource Auto-Proxying

1

2

The DataSource auto-proxying capability automatically wraps Spring DataSource beans with Seata transaction proxies, enabling transparent distributed transaction management for AT (Automatic Transaction) and XA modes. This eliminates the need for manual DataSource proxy configuration.

3

4

## Installation and Setup

5

6

Auto-proxying is enabled by default when DataSource beans are present:

7

8

```properties

9

# Enable DataSource auto-proxying (default: true)

10

seata.enable-auto-data-source-proxy=true

11

12

# Set proxy mode: AT (default) or XA

13

seata.data-source-proxy-mode=AT

14

15

# Use JDK dynamic proxy instead of CGLIB (default: false)

16

seata.use-jdk-proxy=false

17

```

18

19

## Core Components

20

21

### SeataAutoDataSourceProxyCreator Bean

22

23

The main component that creates DataSource proxies automatically.

24

25

```java { .api }

26

@Bean("seataAutoDataSourceProxyCreator")

27

public static SeataAutoDataSourceProxyCreator seataAutoDataSourceProxyCreator(

28

SeataProperties seataProperties

29

);

30

```

31

32

**Parameters:**

33

- `seataProperties`: Main Seata configuration properties containing proxy settings

34

35

**Returns:** `SeataAutoDataSourceProxyCreator` - Proxy creator that wraps DataSource beans

36

37

## Automatic DataSource Wrapping

38

39

### Basic DataSource Configuration

40

41

Your existing DataSource beans are automatically wrapped:

42

43

```java

44

@Configuration

45

public class DataSourceConfig {

46

47

@Bean

48

@Primary

49

public DataSource primaryDataSource() {

50

HikariConfig config = new HikariConfig();

51

config.setJdbcUrl("jdbc:mysql://localhost:3306/order_db");

52

config.setUsername("user");

53

config.setPassword("password");

54

return new HikariDataSource(config);

55

}

56

57

@Bean("inventoryDataSource")

58

public DataSource inventoryDataSource() {

59

HikariConfig config = new HikariConfig();

60

config.setJdbcUrl("jdbc:mysql://localhost:3306/inventory_db");

61

config.setUsername("user");

62

config.setPassword("password");

63

return new HikariDataSource(config);

64

}

65

66

// Both DataSources will be automatically proxied by Seata

67

// No additional configuration required

68

}

69

```

70

71

### Multiple DataSource Support

72

73

All DataSource beans in the application context are automatically proxied:

74

75

```java

76

@Service

77

public class OrderService {

78

79

@Autowired

80

@Qualifier("primaryDataSource")

81

private DataSource orderDataSource;

82

83

@Autowired

84

@Qualifier("inventoryDataSource")

85

private DataSource inventoryDataSource;

86

87

@GlobalTransactional

88

public void processOrder() {

89

// Both DataSources participate in the same distributed transaction

90

try (Connection orderConn = orderDataSource.getConnection();

91

Connection inventoryConn = inventoryDataSource.getConnection()) {

92

93

// Operations on both connections are coordinated

94

insertOrder(orderConn);

95

updateInventory(inventoryConn);

96

97

// If either operation fails, both will be rolled back

98

}

99

}

100

}

101

```

102

103

## Transaction Modes

104

105

### AT (Automatic Transaction) Mode

106

107

The default mode that provides automatic transaction management through SQL interception:

108

109

```properties

110

# AT mode configuration (default)

111

seata.data-source-proxy-mode=AT

112

113

# AT mode automatically handles:

114

# - SQL interception and modification

115

# - Undo log generation for rollback

116

# - Lock management for isolation

117

```

118

119

**Benefits:**

120

- Zero business logic intrusion

121

- Automatic rollback through undo logs

122

- High performance for most scenarios

123

124

**Requirements:**

125

- Primary key required for all tables

126

- Undo log table (`undo_log`) must exist

127

128

### XA Mode

129

130

Standards-based XA protocol support for strict ACID compliance:

131

132

```properties

133

# XA mode configuration

134

seata.data-source-proxy-mode=XA

135

136

# XA mode provides:

137

# - Standards-based two-phase commit

138

# - Strong consistency guarantees

139

# - Database-level transaction coordination

140

```

141

142

**Benefits:**

143

- Industry standard XA protocol

144

- Strong consistency guarantees

145

- No undo log requirements

146

147

**Requirements:**

148

- Database must support XA transactions

149

- Higher resource consumption

150

- Potential performance impact

151

152

## Configuration Properties

153

154

### DataSource Proxy Configuration

155

156

```java { .api }

157

public class SeataProperties {

158

// Enable automatic DataSource proxying

159

private boolean enableAutoDataSourceProxy = true;

160

161

// DataSource proxy mode: AT or XA

162

private String dataSourceProxyMode = "AT";

163

164

// Use JDK dynamic proxy instead of CGLIB

165

private boolean useJdkProxy = false;

166

167

// DataSource bean names to exclude from proxying

168

private String[] excludesForAutoProxying = {};

169

}

170

```

171

172

### Exclusions Configuration

173

174

Exclude specific DataSource beans from automatic proxying:

175

176

```properties

177

# Exclude specific DataSource beans by name

178

seata.excludes-for-auto-proxying=testDataSource,cacheDataSource

179

```

180

181

```java

182

@Configuration

183

public class DataSourceConfig {

184

185

@Bean

186

@Primary

187

public DataSource primaryDataSource() {

188

// This will be automatically proxied

189

return new HikariDataSource();

190

}

191

192

@Bean("testDataSource")

193

public DataSource testDataSource() {

194

// This will be excluded from proxying (configured in properties)

195

return new HikariDataSource();

196

}

197

}

198

```

199

200

## Auto-Configuration Details

201

202

DataSource auto-proxying is configured through `SeataDataSourceAutoConfiguration`:

203

204

```java { .api }

205

@Configuration(proxyBeanMethods = false)

206

@ConditionalOnExpression("${seata.enabled:true} && ${seata.enableAutoDataSourceProxy:true} && ${seata.enable-auto-data-source-proxy:true}")

207

@ConditionalOnBean(DataSource.class)

208

@AutoConfigureOrder(Ordered.LOWEST_PRECEDENCE)

209

@AutoConfigureAfter(value = {SeataCoreAutoConfiguration.class},

210

name = "org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration")

211

public class SeataDataSourceAutoConfiguration {

212

213

@Bean("seataAutoDataSourceProxyCreator")

214

@ConditionalOnMissingBean(SeataAutoDataSourceProxyCreator.class)

215

public static SeataAutoDataSourceProxyCreator seataAutoDataSourceProxyCreator(

216

SeataProperties seataProperties

217

);

218

}

219

```

220

221

**Activation Conditions:**

222

- `seata.enabled=true` (default)

223

- `seata.enableAutoDataSourceProxy=true` (default)

224

- At least one DataSource bean must be present

225

- Runs after core Seata auto-configuration

226

227

## JdbcTemplate Integration

228

229

DataSource proxying works seamlessly with Spring's JdbcTemplate:

230

231

```java

232

@Service

233

public class OrderService {

234

235

@Autowired

236

private JdbcTemplate jdbcTemplate;

237

238

@GlobalTransactional

239

public void createOrder(Order order) {

240

// JdbcTemplate uses the proxied DataSource automatically

241

String sql = "INSERT INTO orders (id, customer_id, amount) VALUES (?, ?, ?)";

242

jdbcTemplate.update(sql, order.getId(), order.getCustomerId(), order.getAmount());

243

244

// Transaction coordinates with other services

245

paymentService.processPayment(order.getAmount());

246

inventoryService.reserveItems(order.getItems());

247

}

248

}

249

```

250

251

## JPA/Hibernate Integration

252

253

Works with JPA EntityManager and Hibernate:

254

255

```java

256

@Entity

257

@Table(name = "orders")

258

public class Order {

259

@Id

260

private Long id;

261

private String customerId;

262

private BigDecimal amount;

263

// ... other fields

264

}

265

266

@Repository

267

public class OrderRepository {

268

269

@PersistenceContext

270

private EntityManager entityManager;

271

272

@GlobalTransactional

273

public void saveOrder(Order order) {

274

// EntityManager uses proxied DataSource

275

entityManager.persist(order);

276

277

// Distributed transaction coordination happens automatically

278

inventoryService.updateStock(order.getItems());

279

}

280

}

281

```

282

283

## Connection Pool Integration

284

285

Auto-proxying works with popular connection pools:

286

287

### HikariCP Configuration

288

289

```java

290

@Configuration

291

public class HikariDataSourceConfig {

292

293

@Bean

294

@ConfigurationProperties("spring.datasource.hikari")

295

public DataSource dataSource() {

296

// HikariCP DataSource will be automatically proxied

297

return DataSourceBuilder.create()

298

.type(HikariDataSource.class)

299

.build();

300

}

301

}

302

```

303

304

### Druid Configuration

305

306

```java

307

@Configuration

308

public class DruidDataSourceConfig {

309

310

@Bean

311

@ConfigurationProperties("spring.datasource.druid")

312

public DataSource dataSource() {

313

// Druid DataSource will be automatically proxied

314

return DruidDataSourceBuilder.create().build();

315

}

316

}

317

```

318

319

## Manual Proxy Creation (Alternative)

320

321

If you need manual control over DataSource proxying:

322

323

```java

324

@Configuration

325

public class ManualDataSourceConfig {

326

327

@Bean

328

@Primary

329

public DataSource dataSource() {

330

HikariDataSource originalDataSource = new HikariDataSource();

331

// Configure original DataSource...

332

333

// Manually create Seata proxy

334

return SeataDataSourceProxy.wrap(originalDataSource);

335

}

336

}

337

```

338

339

Disable auto-proxying when using manual proxies:

340

341

```properties

342

seata.enable-auto-data-source-proxy=false

343

```

344

345

## Performance Considerations

346

347

### AT Mode Performance

348

349

- **SQL Interception**: Minimal overhead for SQL parsing and modification

350

- **Undo Logs**: Additional storage and I/O for rollback capability

351

- **Lock Management**: Efficient optimistic locking with conflict detection

352

353

### XA Mode Performance

354

355

- **Two-Phase Commit**: Higher latency due to additional coordination phases

356

- **Resource Locking**: Longer lock holding times affecting concurrency

357

- **Network Overhead**: Additional communication with transaction coordinator

358

359

### Optimization Tips

360

361

```properties

362

# Connection pool optimization for Seata

363

spring.datasource.hikari.maximum-pool-size=20

364

spring.datasource.hikari.minimum-idle=5

365

spring.datasource.hikari.connection-timeout=60000

366

367

# AT mode optimization

368

seata.client.undo.log-serialization=jackson

369

seata.client.undo.compress.enable=true

370

```

371

372

## Troubleshooting

373

374

### Common Issues

375

376

1. **DataSource Not Proxied**: Check auto-configuration conditions and bean registration

377

2. **Connection Pool Issues**: Verify connection pool configuration and limits

378

3. **Transaction Isolation**: Review database isolation levels for AT mode

379

4. **Undo Log Errors**: Ensure undo_log table exists and is properly configured

380

381

### Debug Configuration

382

383

```properties

384

# Debug DataSource proxying

385

logging.level.io.seata.rm.datasource=DEBUG

386

logging.level.io.seata.spring.annotation.datasource=DEBUG

387

388

# Monitor connection usage

389

spring.datasource.hikari.leak-detection-threshold=60000

390

```

391

392

### Undo Log Table Setup

393

394

For AT mode, create the required undo log table:

395

396

```sql

397

-- MySQL example

398

CREATE TABLE `undo_log` (

399

`id` bigint(20) NOT NULL AUTO_INCREMENT,

400

`branch_id` bigint(20) NOT NULL,

401

`xid` varchar(100) NOT NULL,

402

`context` varchar(128) NOT NULL,

403

`rollback_info` longblob NOT NULL,

404

`log_status` int(11) NOT NULL,

405

`log_created` datetime NOT NULL,

406

`log_modified` datetime NOT NULL,

407

PRIMARY KEY (`id`),

408

UNIQUE KEY `ux_undo_log` (`xid`,`branch_id`)

409

) ENGINE=InnoDB DEFAULT CHARSET=utf8;

410

```