or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

configuration.mdexceptions.mdindex.mdquery-building.mdquery-execution.mdrecords.mdschema-objects.mdutilities.md

exceptions.mddocs/

0

# Exception Handling

1

2

jOOQ-specific exception hierarchy for handling database errors, data access issues, and configuration problems with detailed error information and recovery strategies.

3

4

## Capabilities

5

6

### Base Exception Classes

7

8

Core exception hierarchy providing structured error handling for database operations.

9

10

```java { .api }

11

/**

12

* Base exception for all database access errors in jOOQ

13

* Runtime exception that wraps SQL exceptions and provides additional context

14

*/

15

public class DataAccessException extends RuntimeException {

16

/**

17

* Create exception with message

18

* @param message Error message

19

*/

20

public DataAccessException(String message);

21

22

/**

23

* Create exception with message and cause

24

* @param message Error message

25

* @param cause Underlying cause

26

*/

27

public DataAccessException(String message, Throwable cause);

28

29

/**

30

* Get the underlying SQL state if available

31

* @return SQL state from SQLException or null

32

*/

33

public String sqlState();

34

35

/**

36

* Get the underlying SQL error code if available

37

* @return SQL error code from SQLException or 0

38

*/

39

public int sqlErrorCode();

40

41

/**

42

* Get the SQL that caused this exception if available

43

* @return SQL string or null

44

*/

45

public String sql();

46

}

47

48

/**

49

* Exception for database definition (DDL) related errors

50

* Thrown when DDL operations fail or are invalid

51

*/

52

public class DataDefinitionException extends DataAccessException {

53

/**

54

* Create exception with message

55

* @param message Error message

56

*/

57

public DataDefinitionException(String message);

58

59

/**

60

* Create exception with message and cause

61

* @param message Error message

62

* @param cause Underlying cause

63

*/

64

public DataDefinitionException(String message, Throwable cause);

65

}

66

67

/**

68

* Base exception for configuration-related errors

69

* Thrown when jOOQ configuration is invalid or incomplete

70

*/

71

public class ConfigurationException extends DataAccessException {

72

/**

73

* Create exception with message

74

* @param message Error message

75

*/

76

public ConfigurationException(String message);

77

78

/**

79

* Create exception with message and cause

80

* @param message Error message

81

* @param cause Underlying cause

82

*/

83

public ConfigurationException(String message, Throwable cause);

84

}

85

```

86

87

### Query Result Exceptions

88

89

Exceptions related to unexpected query results or data validation failures.

90

91

```java { .api }

92

/**

93

* Base exception for invalid query results

94

* Thrown when query results don't match expectations

95

*/

96

public class InvalidResultException extends DataAccessException {

97

/**

98

* Create exception with message

99

* @param message Error message

100

*/

101

public InvalidResultException(String message);

102

103

/**

104

* Create exception with message and cause

105

* @param message Error message

106

* @param cause Underlying cause

107

*/

108

public InvalidResultException(String message, Throwable cause);

109

}

110

111

/**

112

* Exception thrown when no data is found but was expected

113

* Commonly thrown by fetchOne() when no records match

114

*/

115

public class NoDataFoundException extends InvalidResultException {

116

/**

117

* Create exception with default message

118

*/

119

public NoDataFoundException();

120

121

/**

122

* Create exception with custom message

123

* @param message Error message

124

*/

125

public NoDataFoundException(String message);

126

127

/**

128

* Create exception with message and cause

129

* @param message Error message

130

* @param cause Underlying cause

131

*/

132

public NoDataFoundException(String message, Throwable cause);

133

}

134

135

/**

136

* Exception thrown when more rows are returned than expected

137

* Commonly thrown by fetchOne() when multiple records match

138

*/

139

public class TooManyRowsException extends InvalidResultException {

140

/**

141

* Create exception with default message

142

*/

143

public TooManyRowsException();

144

145

/**

146

* Create exception with custom message

147

* @param message Error message

148

*/

149

public TooManyRowsException(String message);

150

151

/**

152

* Create exception with message and cause

153

* @param message Error message

154

* @param cause Underlying cause

155

*/

156

public TooManyRowsException(String message, Throwable cause);

157

158

/**

159

* Get the number of rows that were found

160

* @return Actual row count

161

*/

162

public int getRowCount();

163

}

164

165

/**

166

* Exception for data integrity constraint violations

167

* Thrown when database constraints are violated during DML operations

168

*/

169

public class DataChangedException extends DataAccessException {

170

/**

171

* Create exception with message

172

* @param message Error message

173

*/

174

public DataChangedException(String message);

175

176

/**

177

* Create exception with message and cause

178

* @param message Error message

179

* @param cause Underlying cause

180

*/

181

public DataChangedException(String message, Throwable cause);

182

}

183

```

184

185

### Mapping and Type Conversion Exceptions

186

187

Exceptions related to record mapping and data type conversions.

188

189

```java { .api }

190

/**

191

* Exception for record mapping errors

192

* Thrown when records cannot be mapped to POJOs or other types

193

*/

194

public class MappingException extends DataAccessException {

195

/**

196

* Create exception with message

197

* @param message Error message

198

*/

199

public MappingException(String message);

200

201

/**

202

* Create exception with message and cause

203

* @param message Error message

204

* @param cause Underlying cause

205

*/

206

public MappingException(String message, Throwable cause);

207

}

208

209

/**

210

* Exception for data type conversion errors

211

* Thrown when values cannot be converted between Java and SQL types

212

*/

213

public class DataTypeException extends DataAccessException {

214

/**

215

* Create exception with message

216

* @param message Error message

217

*/

218

public DataTypeException(String message);

219

220

/**

221

* Create exception with message and cause

222

* @param message Error message

223

* @param cause Underlying cause

224

*/

225

public DataTypeException(String message, Throwable cause);

226

}

227

```

228

229

**Usage Examples:**

230

231

```java

232

// Handling specific jOOQ exceptions

233

try {

234

// Expect exactly one record

235

AuthorRecord author = create.selectFrom(AUTHOR)

236

.where(AUTHOR.EMAIL.eq("user@example.com"))

237

.fetchOne();

238

239

} catch (NoDataFoundException e) {

240

// No author found with that email

241

System.out.println("Author not found: " + e.getMessage());

242

243

} catch (TooManyRowsException e) {

244

// Multiple authors found (data integrity issue)

245

System.out.println("Multiple authors found: " + e.getRowCount());

246

247

} catch (DataAccessException e) {

248

// General database error

249

System.out.println("Database error: " + e.getMessage());

250

System.out.println("SQL State: " + e.sqlState());

251

System.out.println("SQL Error Code: " + e.sqlErrorCode());

252

}

253

254

// Handling mapping exceptions

255

try {

256

List<AuthorPojo> authors = create.selectFrom(AUTHOR)

257

.fetch()

258

.into(AuthorPojo.class);

259

260

} catch (MappingException e) {

261

System.out.println("Failed to map records to POJO: " + e.getMessage());

262

}

263

264

// Handling constraint violations

265

try {

266

create.insertInto(AUTHOR)

267

.set(AUTHOR.EMAIL, "duplicate@example.com") // Violates unique constraint

268

.execute();

269

270

} catch (DataChangedException e) {

271

System.out.println("Constraint violation: " + e.getMessage());

272

}

273

```

274

275

### Exception Context and Information

276

277

Additional information available in jOOQ exceptions for debugging and error recovery.

278

279

```java { .api }

280

public interface ExecuteContext {

281

/**

282

* Get the SQL that was being executed when exception occurred

283

* @return SQL string

284

*/

285

String sql();

286

287

/**

288

* Get the bind values that were used

289

* @return Array of bind values

290

*/

291

Object[] bindings();

292

293

/**

294

* Get the SQLException that caused the error

295

* @return Original SQLException or null

296

*/

297

SQLException sqlException();

298

299

/**

300

* Get the execution time before the exception

301

* @return Execution time in nanoseconds

302

*/

303

long executionTime();

304

305

/**

306

* Get the connection that was being used

307

* @return JDBC Connection

308

*/

309

Connection connection();

310

311

/**

312

* Get the configuration context

313

* @return Configuration instance

314

*/

315

Configuration configuration();

316

}

317

```

318

319

### Error Recovery Strategies

320

321

Common patterns for handling and recovering from jOOQ exceptions.

322

323

**Usage Examples:**

324

325

```java

326

// Graceful degradation for optional data

327

public Optional<AuthorRecord> findAuthorByEmail(String email) {

328

try {

329

return Optional.of(

330

create.selectFrom(AUTHOR)

331

.where(AUTHOR.EMAIL.eq(email))

332

.fetchOne()

333

);

334

} catch (NoDataFoundException e) {

335

return Optional.empty();

336

}

337

}

338

339

// Retry logic for transient errors

340

public void updateAuthorWithRetry(int authorId, String newName) {

341

int maxRetries = 3;

342

int retryCount = 0;

343

344

while (retryCount < maxRetries) {

345

try {

346

create.update(AUTHOR)

347

.set(AUTHOR.FIRST_NAME, newName)

348

.where(AUTHOR.ID.eq(authorId))

349

.execute();

350

return; // Success

351

352

} catch (DataAccessException e) {

353

retryCount++;

354

if (retryCount >= maxRetries) {

355

throw e; // Give up after max retries

356

}

357

358

// Wait before retry

359

try {

360

Thread.sleep(1000 * retryCount);

361

} catch (InterruptedException ie) {

362

Thread.currentThread().interrupt();

363

throw new RuntimeException("Interrupted during retry", ie);

364

}

365

}

366

}

367

}

368

369

// Safe batch operations with partial failure handling

370

public List<String> batchInsertAuthors(List<AuthorPojo> authors) {

371

List<String> errors = new ArrayList<>();

372

373

for (AuthorPojo author : authors) {

374

try {

375

create.insertInto(AUTHOR)

376

.set(AUTHOR.FIRST_NAME, author.getFirstName())

377

.set(AUTHOR.LAST_NAME, author.getLastName())

378

.set(AUTHOR.EMAIL, author.getEmail())

379

.execute();

380

381

} catch (DataChangedException e) {

382

// Log constraint violation but continue with other records

383

errors.add("Failed to insert " + author.getEmail() + ": " + e.getMessage());

384

385

} catch (DataAccessException e) {

386

// Log general error but continue

387

errors.add("Database error for " + author.getEmail() + ": " + e.getMessage());

388

}

389

}

390

391

return errors;

392

}

393

394

// Connection recovery for connection pool issues

395

public <T> T executeWithConnectionRecovery(Function<DSLContext, T> operation) {

396

try {

397

return operation.apply(create);

398

399

} catch (DataAccessException e) {

400

// Check if it's a connection-related error

401

if (e.sqlState() != null && e.sqlState().startsWith("08")) {

402

// Connection error - try to get a new connection

403

try (CloseableDSLContext newCreate = using(dataSource, SQLDialect.POSTGRES)) {

404

return operation.apply(newCreate);

405

}

406

}

407

throw e; // Re-throw if not connection-related

408

}

409

}

410

```

411

412

### Custom Exception Handling

413

414

Patterns for creating application-specific exception handling around jOOQ.

415

416

```java { .api }

417

// Custom exception wrapper

418

public class AuthorServiceException extends RuntimeException {

419

private final String sqlState;

420

private final int errorCode;

421

422

public AuthorServiceException(String message, DataAccessException cause) {

423

super(message, cause);

424

this.sqlState = cause.sqlState();

425

this.errorCode = cause.sqlErrorCode();

426

}

427

428

public String getSqlState() { return sqlState; }

429

public int getErrorCode() { return errorCode; }

430

431

public boolean isConstraintViolation() {

432

return "23000".equals(sqlState) || "23505".equals(sqlState);

433

}

434

435

public boolean isConnectionError() {

436

return sqlState != null && sqlState.startsWith("08");

437

}

438

}

439

440

// Service layer exception translation

441

public class AuthorService {

442

private final DSLContext create;

443

444

public AuthorRecord createAuthor(String firstName, String lastName, String email) {

445

try {

446

return create.insertInto(AUTHOR)

447

.set(AUTHOR.FIRST_NAME, firstName)

448

.set(AUTHOR.LAST_NAME, lastName)

449

.set(AUTHOR.EMAIL, email)

450

.returning()

451

.fetchOne();

452

453

} catch (DataChangedException e) {

454

if (e.sqlState() != null && e.sqlState().equals("23505")) {

455

throw new AuthorServiceException("Email already exists: " + email, e);

456

}

457

throw new AuthorServiceException("Failed to create author", e);

458

459

} catch (DataAccessException e) {

460

throw new AuthorServiceException("Database error while creating author", e);

461

}

462

}

463

}

464

```