or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

expression-builders.mdgraph-operations.mdindex.mdmodel-definition.mdquery-building.mdrelationships.mdtransactions.mdutilities.mdvalidation.md

transactions.mddocs/

0

# Transactions

1

2

Database transaction management with model binding and automatic rollback.

3

4

## Capabilities

5

6

### Transaction Function

7

8

Create and manage database transactions with automatic rollback on errors.

9

10

```javascript { .api }

11

/**

12

* Execute callback within a database transaction

13

* @param callback - Function to execute within transaction

14

* @returns Promise resolving to callback result

15

*/

16

function transaction<T>(

17

callback: (trx: Transaction) => Promise<T>

18

): Promise<T>;

19

20

/**

21

* Execute callback within a transaction using specific Knex instance

22

* @param knex - Knex instance to use for transaction

23

* @param callback - Function to execute within transaction

24

* @returns Promise resolving to callback result

25

*/

26

function transaction<T>(

27

knex: Knex,

28

callback: (trx: Transaction) => Promise<T>

29

): Promise<T>;

30

31

/**

32

* Execute callback with bound model classes

33

* @param modelClass - Model class to bind to transaction

34

* @param callback - Function receiving bound model class

35

* @returns Promise resolving to callback result

36

*/

37

function transaction<T>(

38

modelClass: typeof Model,

39

callback: (BoundModel: typeof Model, trx?: Transaction) => Promise<T>

40

): Promise<T>;

41

42

/**

43

* Execute callback with multiple bound model classes

44

*/

45

function transaction<T>(

46

modelClass1: typeof Model,

47

modelClass2: typeof Model,

48

callback: (BoundModel1: typeof Model, BoundModel2: typeof Model, trx?: Transaction) => Promise<T>

49

): Promise<T>;

50

```

51

52

**Usage Examples:**

53

54

```javascript

55

const { transaction, Model } = require('objection');

56

57

// Basic transaction

58

const result = await transaction(async (trx) => {

59

const person = await Person.query(trx)

60

.insert({ firstName: 'John', lastName: 'Doe' });

61

62

const pet = await Pet.query(trx)

63

.insert({ name: 'Fluffy', ownerId: person.id });

64

65

return { person, pet };

66

});

67

68

// Transaction with specific Knex instance

69

const result = await transaction(knex, async (trx) => {

70

// Operations using the provided knex instance

71

const person = await Person.query(trx).insert(personData);

72

return person;

73

});

74

75

// Transaction with bound model classes

76

const result = await transaction(Person, Pet, async (BoundPerson, BoundPet, trx) => {

77

// BoundPerson and BoundPet are automatically bound to the transaction

78

const person = await BoundPerson.query().insert(personData);

79

const pet = await BoundPet.query().insert({ ...petData, ownerId: person.id });

80

81

return { person, pet };

82

});

83

```

84

85

### Model Transaction Methods

86

87

Transaction-related methods available on model classes.

88

89

```javascript { .api }

90

/**

91

* Start a new transaction

92

* @param knexOrTransaction - Knex instance or existing transaction

93

* @returns Promise resolving to Transaction

94

*/

95

static startTransaction(knexOrTransaction?: Knex | Transaction): Promise<Transaction>;

96

97

/**

98

* Execute callback within a transaction

99

* @param callback - Function to execute

100

* @returns Promise resolving to callback result

101

*/

102

static transaction<T>(callback: (trx: Transaction) => Promise<T>): Promise<T>;

103

104

/**

105

* Execute callback within a transaction with specific Knex/transaction

106

* @param trxOrKnex - Transaction or Knex instance

107

* @param callback - Function to execute

108

* @returns Promise resolving to callback result

109

*/

110

static transaction<T>(

111

trxOrKnex: Transaction | Knex,

112

callback: (trx: Transaction) => Promise<T>

113

): Promise<T>;

114

115

/**

116

* Bind model class to a Knex instance or transaction

117

* @param trxOrKnex - Transaction or Knex instance to bind

118

* @returns Bound model class

119

*/

120

static bindKnex(trxOrKnex: Transaction | Knex): typeof Model;

121

122

/**

123

* Bind model class to a transaction (alias for bindKnex)

124

* @param trxOrKnex - Transaction or Knex instance to bind

125

* @returns Bound model class

126

*/

127

static bindTransaction(trxOrKnex: Transaction | Knex): typeof Model;

128

```

129

130

**Usage Examples:**

131

132

```javascript

133

// Start transaction manually

134

const trx = await Person.startTransaction();

135

try {

136

const person = await Person.query(trx).insert(personData);

137

const pet = await Pet.query(trx).insert(petData);

138

139

await trx.commit();

140

return { person, pet };

141

} catch (error) {

142

await trx.rollback();

143

throw error;

144

}

145

146

// Model class transaction

147

const result = await Person.transaction(async (trx) => {

148

const person = await Person.query(trx).insert(personData);

149

return person;

150

});

151

152

// Bind model to transaction

153

const trx = await Person.startTransaction();

154

const BoundPerson = Person.bindKnex(trx);

155

156

try {

157

const person = await BoundPerson.query().insert(personData);

158

await trx.commit();

159

} catch (error) {

160

await trx.rollback();

161

throw error;

162

}

163

```

164

165

### Using Transactions with Queries

166

167

Pass transactions to query methods for transaction-aware operations.

168

169

```javascript { .api }

170

/**

171

* Execute query within a transaction

172

* @param trx - Transaction instance

173

* @returns QueryBuilder bound to transaction

174

*/

175

query(trx: Transaction): QueryBuilder;

176

177

/**

178

* Execute related query within a transaction

179

* @param relationName - Relation name

180

* @param trx - Transaction instance

181

* @returns QueryBuilder bound to transaction

182

*/

183

relatedQuery(relationName: string, trx: Transaction): QueryBuilder;

184

```

185

186

**Usage Examples:**

187

188

```javascript

189

await transaction(async (trx) => {

190

// All queries use the same transaction

191

const person = await Person.query(trx)

192

.insert({ firstName: 'John', lastName: 'Doe' });

193

194

const pets = await person.$relatedQuery('pets', trx)

195

.insert([

196

{ name: 'Fluffy', species: 'cat' },

197

{ name: 'Buddy', species: 'dog' }

198

]);

199

200

// Update within transaction

201

await Person.query(trx)

202

.findById(person.id)

203

.patch({ petCount: pets.length });

204

});

205

```

206

207

### Transaction with Graph Operations

208

209

Graph operations automatically participate in transactions.

210

211

**Usage Examples:**

212

213

```javascript

214

await transaction(async (trx) => {

215

// insertGraph uses the transaction

216

const result = await Person.query(trx)

217

.insertGraphAndFetch({

218

firstName: 'Jane',

219

lastName: 'Smith',

220

pets: [

221

{ name: 'Max', species: 'dog' },

222

{ name: 'Luna', species: 'cat' }

223

],

224

movies: [

225

{ title: 'New Movie', year: 2023 }

226

]

227

});

228

229

// All inserts are in the same transaction

230

return result;

231

});

232

```

233

234

### Transaction Error Handling

235

236

Transactions automatically rollback on errors, but you can also handle them explicitly.

237

238

**Usage Examples:**

239

240

```javascript

241

const { DBError, ValidationError } = require('objection');

242

243

try {

244

await transaction(async (trx) => {

245

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

246

const person = await Person.query(trx).insert(personData);

247

const pet = await Pet.query(trx).insert(invalidPetData); // Might fail

248

249

return { person, pet };

250

});

251

} catch (error) {

252

if (error instanceof ValidationError) {

253

console.log('Validation failed:', error.data);

254

} else if (error instanceof DBError) {

255

console.log('Database error:', error.message);

256

}

257

// Transaction was automatically rolled back

258

}

259

```

260

261

### Nested Transactions

262

263

Handle nested transaction calls appropriately.

264

265

**Usage Examples:**

266

267

```javascript

268

await transaction(async (trx) => {

269

const person = await Person.query(trx).insert(personData);

270

271

// Nested transaction - will reuse outer transaction

272

const pets = await transaction(trx, async (innerTrx) => {

273

return Pet.query(innerTrx).insert(petDataArray);

274

});

275

276

return { person, pets };

277

});

278

```

279

280

### Transaction Isolation Levels

281

282

Control transaction isolation levels through Knex configuration.

283

284

**Usage Examples:**

285

286

```javascript

287

// Configure isolation level in knex config

288

const knex = Knex({

289

client: 'postgresql',

290

connection: connectionConfig,

291

pool: {

292

afterCreate: function(conn, done) {

293

conn.query('SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;', done);

294

}

295

}

296

});

297

298

// Or set for specific transaction

299

await transaction(async (trx) => {

300

await trx.raw('SET TRANSACTION ISOLATION LEVEL READ COMMITTED');

301

// Perform operations...

302

});

303

```

304

305

### Transaction Savepoints

306

307

Use savepoints for partial rollbacks within transactions.

308

309

**Usage Examples:**

310

311

```javascript

312

await transaction(async (trx) => {

313

const person = await Person.query(trx).insert(personData);

314

315

const savepoint = await trx.savepoint();

316

317

try {

318

// Risky operation

319

await Pet.query(trx).insert(riskyPetData);

320

await savepoint.release();

321

} catch (error) {

322

// Rollback to savepoint, not entire transaction

323

await savepoint.rollback();

324

console.log('Pet creation failed, but person creation preserved');

325

}

326

327

return person;

328

});

329

```

330

331

## Types

332

333

```typescript { .api }

334

type Transaction = Knex.Transaction;

335

336

interface TransactionConfig {

337

isolationLevel?: 'read uncommitted' | 'read committed' | 'repeatable read' | 'serializable';

338

readOnly?: boolean;

339

}

340

341

interface Savepoint {

342

release(): Promise<void>;

343

rollback(): Promise<void>;

344

}

345

346

type TransactionCallback<T> = (trx: Transaction) => Promise<T>;

347

348

type ModelTransactionCallback<T> = (

349

BoundModel: typeof Model,

350

trx?: Transaction

351

) => Promise<T>;

352

```