or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

batch-operations.mdcore-operations.mddataset.mdindex.mdparameters.mdresult-processing.mdstored-procedures.mdtransactions.md

transactions.mddocs/

0

# Transaction Management

1

2

Comprehensive transaction support with automatic resource management, rollback capabilities, and connection caching for improved performance.

3

4

## Capabilities

5

6

### Transaction Control

7

8

Execute operations within database transactions with automatic rollback on exceptions.

9

10

```java { .api }

11

// Execute closure within transaction

12

public Object withTransaction(Closure closure) throws SQLException;

13

14

// Manual transaction control

15

public void commit() throws SQLException;

16

public void rollback() throws SQLException;

17

```

18

19

**Example**:

20

```groovy

21

// Automatic transaction management

22

sql.withTransaction {

23

sql.executeUpdate('INSERT INTO accounts (id, balance) VALUES (1, 1000)')

24

sql.executeUpdate('INSERT INTO accounts (id, balance) VALUES (2, 500)')

25

26

// Transfer money between accounts

27

sql.executeUpdate('UPDATE accounts SET balance = balance - ? WHERE id = ?', [100, 1])

28

sql.executeUpdate('UPDATE accounts SET balance = balance + ? WHERE id = ?', [100, 2])

29

30

// If any operation fails, entire transaction is rolled back

31

}

32

33

// Manual transaction control

34

try {

35

sql.executeUpdate('INSERT INTO orders (customer_id, total) VALUES (?, ?)', [customerId, total])

36

def orderId = sql.firstRow('SELECT LAST_INSERT_ID() as id').id

37

38

orderItems.each { item ->

39

sql.executeUpdate('INSERT INTO order_items (order_id, product_id, quantity) VALUES (?, ?, ?)',

40

[orderId, item.productId, item.quantity])

41

}

42

43

sql.commit()

44

} catch (Exception e) {

45

sql.rollback()

46

throw e

47

}

48

```

49

50

### Connection Caching

51

52

Cache database connections across multiple operations for improved performance.

53

54

```java { .api }

55

// Cache connection during closure execution

56

public Object cacheConnection(Closure closure) throws SQLException;

57

58

// Access cached connection

59

public Connection getConnection() throws SQLException;

60

public DataSource getDataSource();

61

```

62

63

**Example**:

64

```groovy

65

// Cache connection for multiple operations

66

sql.cacheConnection {

67

// All operations in this block reuse the same connection

68

def users = sql.rows('SELECT * FROM users')

69

users.each { user ->

70

sql.executeUpdate('UPDATE user_stats SET last_seen = NOW() WHERE user_id = ?', [user.id])

71

}

72

73

// Update summary statistics

74

sql.executeUpdate('UPDATE system_stats SET total_users = (SELECT COUNT(*) FROM users)')

75

}

76

77

// Without caching, each operation would get a new connection from pool

78

```

79

80

### ResultSet Configuration

81

82

Configure ResultSet properties for scrolling, concurrency, and holdability.

83

84

```java { .api }

85

// ResultSet type (scrollability)

86

public int getResultSetType();

87

public void setResultSetType(int resultSetType);

88

89

// ResultSet concurrency (updatability)

90

public int getResultSetConcurrency();

91

public void setResultSetConcurrency(int resultSetConcurrency);

92

93

// ResultSet holdability (transaction behavior)

94

public int getResultSetHoldability();

95

public void setResultSetHoldability(int resultSetHoldability);

96

```

97

98

**Example**:

99

```groovy

100

import java.sql.ResultSet

101

102

// Configure for scrollable, updatable ResultSet

103

sql.resultSetType = ResultSet.TYPE_SCROLL_INSENSITIVE

104

sql.resultSetConcurrency = ResultSet.CONCUR_UPDATABLE

105

106

sql.query('SELECT * FROM users') { rs ->

107

// Can scroll backwards and forwards

108

rs.last()

109

println "Total rows: ${rs.row}"

110

111

rs.first()

112

while (rs.next()) {

113

if (rs.getString('email') == null) {

114

// Can update directly in ResultSet

115

rs.updateString('email', 'no-email@example.com')

116

rs.updateRow()

117

}

118

}

119

}

120

121

// Configure holdability

122

sql.resultSetHoldability = ResultSet.HOLD_CURSORS_OVER_COMMIT

123

```

124

125

### Statement Caching

126

127

Cache prepared statements for improved performance with repeated queries.

128

129

```java { .api }

130

// Statement caching configuration

131

public boolean isCacheStatements();

132

public void setCacheStatements(boolean cacheStatements);

133

134

// Execute with cached statements

135

public Object cacheStatements(Closure closure) throws SQLException;

136

137

// Statement configuration hooks

138

public Object withStatement(Closure configureStatement) throws SQLException;

139

public Object withCleanupStatement(Closure cleanupStatement) throws SQLException;

140

```

141

142

**Example**:

143

```groovy

144

// Enable statement caching

145

sql.cacheStatements = true

146

147

// Cached statements will be reused for identical SQL

148

def userIds = [1, 2, 3, 4, 5]

149

userIds.each { id ->

150

// Same PreparedStatement reused for each call

151

def user = sql.firstRow('SELECT * FROM users WHERE id = ?', [id])

152

println user.name

153

}

154

155

// Temporary statement caching

156

sql.cacheStatements {

157

// Statements cached only within this block

158

100.times { i ->

159

sql.executeUpdate('INSERT INTO temp_data (value) VALUES (?)', [i])

160

}

161

}

162

163

// Configure statement properties

164

sql.withStatement { stmt ->

165

stmt.queryTimeout = 30

166

stmt.fetchSize = 1000

167

stmt.maxRows = 10000

168

} {

169

def results = sql.rows('SELECT * FROM large_table')

170

// Statement configured for this operation

171

}

172

```

173

174

### Named Query Caching

175

176

Cache parsed named queries for improved performance with parameterized SQL.

177

178

```java { .api }

179

// Named query configuration

180

public boolean isEnableNamedQueries();

181

public void setEnableNamedQueries(boolean enableNamedQueries);

182

public boolean isCacheNamedQueries();

183

public void setCacheNamedQueries(boolean cacheNamedQueries);

184

```

185

186

**Example**:

187

```groovy

188

// Enable named query support and caching

189

sql.enableNamedQueries = true

190

sql.cacheNamedQueries = true

191

192

// Named parameters are parsed and cached

193

def params = [minAge: 25, dept: 'Engineering']

194

sql.eachRow('SELECT * FROM users WHERE age >= :minAge AND department = :dept', params) { row ->

195

println "${row.name} - ${row.department}"

196

}

197

198

// Query parsing is cached for subsequent calls

199

def otherParams = [minAge: 30, dept: 'Sales']

200

sql.eachRow('SELECT * FROM users WHERE age >= :minAge AND department = :dept', otherParams) { row ->

201

println "${row.name} - ${row.department}"

202

}

203

```

204

205

### Connection Pool Integration

206

207

Work effectively with connection pools and DataSource configurations.

208

209

**Example**:

210

```groovy

211

import org.apache.commons.dbcp2.BasicDataSource

212

213

// Configure connection pool

214

def dataSource = new BasicDataSource()

215

dataSource.url = 'jdbc:mysql://localhost:3306/mydb'

216

dataSource.username = 'user'

217

dataSource.password = 'pass'

218

dataSource.driverClassName = 'com.mysql.cj.jdbc.Driver'

219

dataSource.initialSize = 5

220

dataSource.maxTotal = 20

221

dataSource.maxIdle = 10

222

dataSource.minIdle = 5

223

224

def sql = new Sql(dataSource)

225

226

// Use within transactions to ensure connection reuse

227

sql.withTransaction {

228

// All operations use same connection from pool

229

def orders = sql.rows('SELECT * FROM orders WHERE date = CURDATE()')

230

orders.each { order ->

231

sql.executeUpdate('UPDATE orders SET status = ? WHERE id = ?', ['processed', order.id])

232

}

233

}

234

235

// Connection automatically returned to pool when transaction completes

236

```

237

238

### Isolation Levels

239

240

Work with transaction isolation levels for concurrent access control.

241

242

**Example**:

243

```groovy

244

import java.sql.Connection

245

246

// Get underlying connection to set isolation level

247

sql.cacheConnection {

248

def conn = sql.connection

249

def originalLevel = conn.transactionIsolation

250

251

try {

252

// Set stricter isolation for critical operations

253

conn.transactionIsolation = Connection.TRANSACTION_SERIALIZABLE

254

255

sql.withTransaction {

256

// Critical financial transaction

257

def balance = sql.firstRow('SELECT balance FROM accounts WHERE id = ?', [accountId]).balance

258

if (balance >= amount) {

259

sql.executeUpdate('UPDATE accounts SET balance = balance - ? WHERE id = ?',

260

[amount, accountId])

261

} else {

262

throw new RuntimeException('Insufficient funds')

263

}

264

}

265

} finally {

266

// Restore original isolation level

267

conn.transactionIsolation = originalLevel

268

}

269

}

270

```