0
# Database Adapters
1
2
Database connectivity and adapter implementations for MySQL, MariaDB, and PostgreSQL with connection pooling, transaction support, and optimized query execution. HibernateTS provides a unified database interface that abstracts vendor-specific differences while maintaining performance.
3
4
## Capabilities
5
6
### Base Database Interface
7
8
Core interface defining the contract for all database adapters.
9
10
```typescript { .api }
11
/**
12
* Base interface for database adapters
13
*/
14
interface DataBaseBase {
15
/**
16
* Execute SQL query with parameter binding
17
* @param cfg - Database configuration
18
* @param queryString - SQL query string
19
* @param params - Optional query parameters
20
* @returns Promise resolving to DatabaseResult
21
*/
22
sqlquery<T>(cfg: DataBaseConfig<ISaveAbleObject>, queryString: string, params?: Array<any>): Promise<DatabaseResult>;
23
24
/**
25
* Execute SELECT query and return typed results
26
* @param queryString - SQL SELECT statement
27
* @param params - Optional query parameters
28
* @returns Promise resolving to array of result objects
29
*/
30
selectQuery<T>(queryString: string, params?: Array<any>): Promise<Array<T>>;
31
32
/**
33
* Close database connection
34
* @returns Promise that resolves when connection is closed
35
*/
36
end(): Promise<void>;
37
}
38
39
/**
40
* Result interface for database operations
41
*/
42
interface DatabaseResult {
43
/** ID of inserted record (for INSERT operations) */
44
insertId: BigInt;
45
/** Number of rows affected by the operation */
46
affectedRows: number;
47
/** Warning status code from database */
48
warningStatus: number;
49
}
50
51
/**
52
* Query strings interface for database-specific SQL generation
53
*/
54
interface QueryStrings {
55
/** Medium text type string for the database */
56
mediumTextStr: string;
57
/** Generate constraint name */
58
constraintName(constraint: any, context: any): string;
59
/** Generate unique constraint SQL */
60
uniqueConstraintSql(constraint: any, name: string | undefined, context: any): string;
61
/** Generate duplicate key update clause */
62
duplicateKeyUpdate(escapedKeys: Array<string>, context: any): string;
63
/** Insert query transformation (optional) */
64
insertQuery?(sql: string, context: any): string;
65
/** Convert values for database-specific types (optional) */
66
convertValue?(val: any, column: any): any;
67
}
68
69
interface DataBaseConfig<T> {
70
/** Primary key field name */
71
modelPrimary: string;
72
/** Database table name */
73
table: string;
74
/** Column definitions */
75
columns: { [key: string]: any };
76
/** Table options */
77
options: any;
78
/** Reference key field name */
79
referenceKey: string;
80
/** Creates new instance of entity */
81
createInstance(): T;
82
}
83
84
interface ISaveAbleObject {
85
[key: string]: any;
86
}
87
```
88
89
### MariaDB/MySQL Adapter
90
91
High-performance adapter for MariaDB and MySQL databases with connection pooling and advanced configuration options.
92
93
```typescript { .api }
94
/**
95
* MariaDB/MySQL database adapter implementation
96
* Provides optimized connectivity for MariaDB and MySQL databases
97
*/
98
class MariaDbBase implements DataBaseBase {
99
/** Query strings implementation for MariaDB */
100
static queryStrings: QueryStrings;
101
/** Query execution counter */
102
static queryCt: number;
103
104
/**
105
* Execute SQL query with MariaDB-specific optimizations
106
*/
107
sqlquery<T>(cfg: DataBaseConfig<ISaveAbleObject>, queryString: string, params?: Array<any>): Promise<DatabaseResult>;
108
109
/**
110
* Execute SELECT query with result streaming support
111
*/
112
selectQuery<T>(queryString: string, params?: Array<any>): Promise<Array<T>>;
113
114
/**
115
* Close MariaDB connection and release pool resources
116
*/
117
end(): Promise<void>;
118
}
119
120
/**
121
* Set default pool configuration for all MariaDB connections
122
* @param opts - Partial MariaDB pool configuration options
123
*/
124
function setMariaDbPoolDefaults(opts: Partial<mariadb.PoolConfig>): void;
125
126
/**
127
* Execute function with auto-managed MariaDB connection pool
128
* @param consumer - Function that receives MariaDB pool instance
129
* @returns Promise resolving to function result
130
*/
131
function withMariaDbPool<T>(consumer: (pool: MariaDbBase) => Promise<T>): Promise<T>;
132
133
// MariaDB-specific types
134
interface mariadb.PoolConfig {
135
/** Database host */
136
host?: string;
137
/** Database port */
138
port?: number;
139
/** Database user */
140
user?: string;
141
/** Database password */
142
password?: string;
143
/** Database name */
144
database?: string;
145
/** Connection timeout in milliseconds */
146
connectTimeout?: number;
147
/** Maximum connections in pool */
148
connectionLimit?: number;
149
/** Minimum connections to maintain */
150
minimumIdle?: number;
151
/** Maximum idle time before connection closure */
152
idleTimeout?: number;
153
/** Enable compression */
154
compress?: boolean;
155
/** SSL configuration */
156
ssl?: boolean | object;
157
}
158
```
159
160
**Usage Examples:**
161
162
```typescript
163
import { MariaDbBase, withMariaDbPool, setMariaDbPoolDefaults } from "hibernatets";
164
165
// Configure default pool settings
166
setMariaDbPoolDefaults({
167
host: process.env.DB_URL,
168
port: parseInt(process.env.DB_PORT || "3306"),
169
user: process.env.DB_USER,
170
password: process.env.DB_PASSWORD,
171
database: process.env.DB_NAME,
172
connectionLimit: 10,
173
minimumIdle: 2,
174
idleTimeout: 300000, // 5 minutes
175
connectTimeout: 10000 // 10 seconds
176
});
177
178
// Using managed pool for operations
179
const results = await withMariaDbPool(async (db) => {
180
const users = await db.selectQuery<User>(
181
"SELECT * FROM users WHERE active = ?",
182
[true]
183
);
184
185
const insertResult = await db.sqlquery(
186
{},
187
"INSERT INTO users (name, email) VALUES (?, ?)",
188
["Alice", "alice@example.com"]
189
);
190
191
return { users, insertId: insertResult.insertId };
192
});
193
194
// Direct adapter usage
195
const db = new MariaDbBase();
196
try {
197
const result = await db.sqlquery(
198
{},
199
"UPDATE users SET last_login = NOW() WHERE id = ?",
200
[123]
201
);
202
console.log(`Updated ${result.affectedRows} rows`);
203
} finally {
204
await db.end();
205
}
206
```
207
208
### MySQL Adapter (Legacy)
209
210
Legacy MySQL adapter using the older MySQL driver for compatibility with existing systems.
211
212
```typescript { .api }
213
/**
214
* MySQL database adapter implementation (legacy driver)
215
* Provides compatibility with older MySQL driver implementations
216
*/
217
class MysqlBase implements DataBaseBase {
218
/** Query strings implementation for MySQL */
219
static queryStrings: QueryStrings;
220
/** Query execution counter */
221
static queryCt: number;
222
223
/**
224
* Execute SQL query with MySQL-specific handling
225
*/
226
sqlquery<T>(cfg: DataBaseConfig<ISaveAbleObject>, queryString: string, params?: Array<any>): Promise<DatabaseResult>;
227
228
/**
229
* Execute SELECT query with MySQL result formatting
230
*/
231
selectQuery<T>(queryString: string, params?: Array<any>): Promise<Array<T>>;
232
233
/**
234
* Close MySQL connection
235
*/
236
end(): Promise<void>;
237
}
238
239
/**
240
* Set default pool configuration for MySQL connections
241
* @param cfg - Partial MySQL pool configuration
242
*/
243
function setMysqlDefaults(cfg: Partial<PoolConfig>): void;
244
245
// MySQL-specific types
246
interface PoolConfig {
247
/** Database host */
248
host?: string;
249
/** Database port */
250
port?: number;
251
/** Database user */
252
user?: string;
253
/** Database password */
254
password?: string;
255
/** Database name */
256
database?: string;
257
/** Connection limit */
258
connectionLimit?: number;
259
/** Enable multiple statements */
260
multipleStatements?: boolean;
261
/** Timezone setting */
262
timezone?: string;
263
}
264
```
265
266
**Usage Examples:**
267
268
```typescript
269
import { MysqlBase, setMysqlDefaults } from "hibernatets";
270
271
// Configure MySQL defaults
272
setMysqlDefaults({
273
host: process.env.DB_URL,
274
port: parseInt(process.env.DB_PORT || "3306"),
275
user: process.env.DB_USER,
276
password: process.env.DB_PASSWORD,
277
database: process.env.DB_NAME,
278
connectionLimit: 15,
279
multipleStatements: false,
280
timezone: "UTC"
281
});
282
283
// Using MySQL adapter
284
const db = new MysqlBase();
285
try {
286
const products = await db.selectQuery<Product>(
287
"SELECT * FROM products WHERE category = ? AND price > ?",
288
["electronics", 100]
289
);
290
291
const updateResult = await db.sqlquery(
292
{},
293
"UPDATE products SET stock = stock - 1 WHERE id = ?",
294
[456]
295
);
296
297
console.log(`Found ${products.length} products, updated ${updateResult.affectedRows} records`);
298
} finally {
299
await db.end();
300
}
301
```
302
303
### PostgreSQL Adapter
304
305
Modern PostgreSQL adapter with advanced features and optimizations for PostgreSQL-specific functionality.
306
307
```typescript { .api }
308
/**
309
* PostgreSQL database adapter implementation
310
* Provides full-featured PostgreSQL connectivity with advanced features
311
*/
312
class PsqlBase implements DataBaseBase {
313
/** Query strings implementation for PostgreSQL */
314
static queryStrings: QueryStrings;
315
/** Query execution counter */
316
static queryCt: number;
317
/**
318
* Execute SQL query with PostgreSQL-specific parameter binding
319
*/
320
sqlquery<T>(cfg: DataBaseConfig<ISaveAbleObject>, queryString: string, params?: Array<any>): Promise<DatabaseResult>;
321
322
/**
323
* Execute SELECT query with PostgreSQL result handling
324
*/
325
selectQuery<T>(queryString: string, params?: Array<any>): Promise<Array<T>>;
326
327
/**
328
* Close PostgreSQL connection
329
*/
330
end(): Promise<void>;
331
}
332
```
333
334
**Usage Examples:**
335
336
```typescript
337
import { PsqlBase } from "hibernatets";
338
339
// Using PostgreSQL adapter
340
const db = new PsqlBase();
341
try {
342
// PostgreSQL-specific features like RETURNING clause
343
const insertResult = await db.sqlquery(
344
{},
345
"INSERT INTO users (name, email) VALUES ($1, $2) RETURNING id",
346
["Bob", "bob@example.com"]
347
);
348
349
// JSON operations (PostgreSQL specific)
350
const jsonUsers = await db.selectQuery<any>(
351
"SELECT id, name, metadata->'preferences' as prefs FROM users WHERE metadata->>'active' = $1",
352
["true"]
353
);
354
355
// Array operations
356
const taggedPosts = await db.selectQuery<Post>(
357
"SELECT * FROM posts WHERE $1 = ANY(tags)",
358
["javascript"]
359
);
360
361
console.log(`Inserted user with ID: ${insertResult.insertId}`);
362
} finally {
363
await db.end();
364
}
365
```
366
367
### Environment Configuration
368
369
Environment variables for database connection configuration across different adapters.
370
371
```typescript { .api }
372
// MariaDB/MySQL Environment Variables
373
interface MariaDBEnvironment {
374
/** Database name */
375
DB_NAME: string;
376
/** Database port (default: 3306) */
377
DB_PORT: string;
378
/** Database user */
379
DB_USER: string;
380
/** Database host URL */
381
DB_URL: string;
382
/** Database password */
383
DB_PASSWORD: string;
384
}
385
386
// PostgreSQL Environment Variables
387
interface PostgreSQLEnvironment {
388
/** PostgreSQL host URL */
389
PSQL_URL: string;
390
/** PostgreSQL port */
391
PSQL_PORT: string;
392
/** PostgreSQL password */
393
PSQL_PWD: string;
394
/** PostgreSQL user (default: "postgres") */
395
PSQL_USER: string;
396
/** PostgreSQL database name */
397
PSQL_DB: string;
398
}
399
```
400
401
**Usage Examples:**
402
403
```typescript
404
// MariaDB/MySQL configuration from environment
405
const mariaDbConfig = {
406
host: process.env.DB_URL,
407
port: parseInt(process.env.DB_PORT || "3306"),
408
user: process.env.DB_USER,
409
password: process.env.DB_PASSWORD,
410
database: process.env.DB_NAME
411
};
412
413
// PostgreSQL configuration from environment
414
const psqlConfig = {
415
host: process.env.PSQL_URL,
416
port: parseInt(process.env.PSQL_PORT || "5432"),
417
user: process.env.PSQL_USER || "postgres",
418
password: process.env.PSQL_PWD,
419
database: process.env.PSQL_DB
420
};
421
```
422
423
### Connection Pool Management
424
425
Advanced patterns for managing database connections and optimizing performance.
426
427
```typescript
428
import { MariaDbBase, withMariaDbPool, setMariaDbPoolDefaults, MysqlBase, setMysqlDefaults, PsqlBase } from "hibernatets";
429
430
// Connection pooling strategies
431
class DatabaseManager {
432
private static mariaDbPool: MariaDbBase;
433
private static mysqlPool: MysqlBase;
434
private static psqlPool: PsqlBase;
435
436
static async initializePools() {
437
// MariaDB pool with custom settings
438
setMariaDbPoolDefaults({
439
connectionLimit: 20,
440
minimumIdle: 5,
441
idleTimeout: 600000, // 10 minutes
442
connectTimeout: 15000, // 15 seconds
443
compress: true
444
});
445
446
// MySQL pool for legacy systems
447
setMysqlDefaults({
448
connectionLimit: 10,
449
timezone: "UTC",
450
multipleStatements: false
451
});
452
453
console.log("Database pools initialized");
454
}
455
456
static async executeWithTransaction<T>(
457
operation: (db: DataBaseBase) => Promise<T>
458
): Promise<T> {
459
return await withMariaDbPool(async (db) => {
460
await db.sqlquery({}, "START TRANSACTION", []);
461
try {
462
const result = await operation(db);
463
await db.sqlquery({}, "COMMIT", []);
464
return result;
465
} catch (error) {
466
await db.sqlquery({}, "ROLLBACK", []);
467
throw error;
468
}
469
});
470
}
471
472
static async healthCheck(): Promise<boolean> {
473
try {
474
await withMariaDbPool(async (db) => {
475
await db.selectQuery("SELECT 1 as health", []);
476
});
477
return true;
478
} catch (error) {
479
console.error("Database health check failed:", error);
480
return false;
481
}
482
}
483
}
484
485
// Usage examples
486
await DatabaseManager.initializePools();
487
488
// Transaction example
489
const result = await DatabaseManager.executeWithTransaction(async (db) => {
490
const user = await db.sqlquery(
491
{},
492
"INSERT INTO users (name, email) VALUES (?, ?)",
493
["Charlie", "charlie@example.com"]
494
);
495
496
await db.sqlquery(
497
{},
498
"INSERT INTO user_profiles (user_id, bio) VALUES (?, ?)",
499
[user.insertId, "Software developer"]
500
);
501
502
return user.insertId;
503
});
504
```
505
506
### Performance Optimization
507
508
Best practices and patterns for optimal database performance with HibernateTS adapters.
509
510
```typescript
511
import { MariaDbBase, withMariaDbPool } from "hibernatets";
512
513
// Batch operations for improved performance
514
class PerformanceOptimizer {
515
static async batchInsert<T>(
516
tableName: string,
517
records: T[],
518
batchSize: number = 1000
519
): Promise<void> {
520
await withMariaDbPool(async (db) => {
521
for (let i = 0; i < records.length; i += batchSize) {
522
const batch = records.slice(i, i + batchSize);
523
const placeholders = batch.map(() => "(?, ?)").join(", ");
524
const values = batch.flatMap(record =>
525
[record.name, record.email]
526
);
527
528
await db.sqlquery(
529
{},
530
`INSERT INTO ${tableName} (name, email) VALUES ${placeholders}`,
531
values
532
);
533
}
534
});
535
}
536
537
static async optimizedBulkUpdate(
538
tableName: string,
539
updates: Array<{ id: number; data: any }>
540
): Promise<void> {
541
await withMariaDbPool(async (db) => {
542
// Use CASE statements for bulk updates
543
const caseStatements = updates.map(update =>
544
`WHEN id = ${update.id} THEN '${update.data.name}'`
545
).join(' ');
546
547
const ids = updates.map(u => u.id).join(',');
548
549
await db.sqlquery(
550
{},
551
`UPDATE ${tableName}
552
SET name = CASE ${caseStatements} END,
553
updated_at = NOW()
554
WHERE id IN (${ids})`,
555
[]
556
);
557
});
558
}
559
560
static async getConnectionStats(): Promise<any> {
561
return await withMariaDbPool(async (db) => {
562
return await db.selectQuery(
563
"SHOW STATUS LIKE 'Threads_%'",
564
[]
565
);
566
});
567
}
568
}
569
```