0
# Data Operations
1
2
Core CRUD operations for loading, saving, and deleting entities with support for relationships, bulk operations, and advanced querying capabilities. HibernateTS provides a comprehensive set of functions for database interaction with full type safety.
3
4
## Capabilities
5
6
### Load Function
7
8
Loads entities from the database with support for deep loading, filtering, and flexible query patterns.
9
10
```typescript { .api }
11
/**
12
* Loads entities from the database with support for deep loading and filtering
13
* @param findClass - Constructor class of the entity to load
14
* @param primaryKeyOrFilter - Primary key, SQL condition, function filter, or LoadParams object
15
* @param parameters - Array of SQL parameters or string parameter
16
* @param options - LoadOptions for controlling loading behavior
17
* @returns Promise resolving to single entity or array of entities
18
*/
19
function load<T>(findClass: ConstructorClass<T>, primaryKeyOrFilter: LoadParams<T, Filter<T>, { first: true } & CustomOmit<LoadOptions<T>, "first">>): Promise<T>;
20
function load<T>(findClass: ConstructorClass<T>, primaryKeyOrFilter: number | LoadParams<T, number>, parameters?: any[], options?: LoadOptions<T>): Promise<T>;
21
function load<T>(findClass: ConstructorClass<T>, primaryKeyOrFilter: string | SqlCondition | LoadParams<T, string>, parameters?: any[], options?: LoadOptions<T>): Promise<Array<T>>;
22
function load<T>(findClass: ConstructorClass<T>, primaryKeyOrFilter: ((obj: T) => any) | LoadParams<T, (obj: T) => any>, parameters?: any[], options?: LoadOptions<T>): Promise<Array<T>>;
23
24
interface LoadOptions<T> {
25
/** Enable deep loading of relationships */
26
deep?: boolean | Array<string | SqlCondition> | { [key: string]: string | SqlCondition | { filter: string | SqlCondition, depths: number } };
27
/** Array of field names to skip during loading */
28
skipFields?: Array<string>;
29
/** Return single result instead of array */
30
first?: boolean;
31
/** Include IDs for non-deep one-to-one relationships */
32
idOnNonDeepOneToOne?: boolean;
33
/** Include shallow reference data */
34
withShallowReferences?: boolean;
35
/** Database connection to use */
36
db?: DataBaseBase;
37
/** Skip automatic setter interception */
38
dontInterceptSetters?: true;
39
/** Enable array function interception */
40
interceptArrayFunctions?: boolean;
41
}
42
43
interface LoadParams<T, F = Filter<T>, O = LoadOptions<T>> {
44
/** Filter condition */
45
filter?: F;
46
/** SQL parameters */
47
params?: Array<string | number> | string;
48
/** Load options */
49
options?: O;
50
}
51
52
interface ConstructorClass<T> {
53
new (...args: any[]): T;
54
}
55
56
interface DataBaseBase {
57
sqlquery<T>(cfg: any, queryString: string, params?: any[]): Promise<any>;
58
selectQuery<T>(queryString: string, params?: any[]): Promise<Array<T>>;
59
end(): Promise<void>;
60
}
61
62
type Filter<T> = SqlCondition | string | number | ((obj: T) => any);
63
```
64
65
**Usage Examples:**
66
67
```typescript
68
import { load, SqlCondition } from "hibernatets";
69
70
// Load by primary key
71
const user = await load(User, 1);
72
73
// Load by primary key with relationships
74
const userWithPosts = await load(User, 1, [], { deep: true });
75
76
// Load multiple users with SQL condition
77
const activeUsers = await load(User,
78
new SqlCondition().column("active").equals(true)
79
);
80
81
// Load with specific deep loading
82
const userWithFilteredPosts = await load(User, 1, [], {
83
deep: {
84
posts: new SqlCondition().column("published").equals(true)
85
}
86
});
87
88
// Load with function filter
89
const youngUsers = await load(User, (user: User) => user.age < 30);
90
91
// Load with LoadParams object
92
const result = await load(User, {
93
filter: new SqlCondition().column("name").equals("Alice"),
94
params: [],
95
options: { deep: true, first: true }
96
});
97
98
// Load with skip fields
99
const usersWithoutSensitiveData = await load(User,
100
SqlCondition.ALL,
101
[],
102
{ skipFields: ["password", "email"] }
103
);
104
```
105
106
### Save Function
107
108
Saves entities to the database with support for relationships, duplicate key handling, and bulk operations.
109
110
```typescript { .api }
111
/**
112
* Saves entities to the database with support for relationships and duplicate key handling
113
* @param saveObjects - Single entity or array of entities to save
114
* @param options - SaveOptions including updateOnDuplicate and db connection
115
* @returns Promise resolving to array of affected row counts
116
*/
117
function save<T>(saveObjects: T | T[], options?: SaveOptions<T>): Promise<Array<number>>;
118
119
interface SaveOptions<T> {
120
/** Handle duplicate keys during save operation */
121
updateOnDuplicate?: boolean | { skip?: Array<keyof T & string> };
122
/** Database connection to use */
123
db?: DataBaseBase;
124
}
125
```
126
127
**Usage Examples:**
128
129
```typescript
130
import { save } from "hibernatets";
131
132
// Save single entity
133
const user = new User();
134
user.name = "Alice";
135
user.email = "alice@example.com";
136
const [insertId] = await save(user);
137
138
// Save multiple entities
139
const users = [
140
Object.assign(new User(), { name: "Bob", email: "bob@example.com" }),
141
Object.assign(new User(), { name: "Charlie", email: "charlie@example.com" })
142
];
143
const insertIds = await save(users);
144
145
// Save with duplicate key handling
146
await save(user, {
147
updateOnDuplicate: true
148
});
149
150
// Save with selective duplicate key handling
151
await save(user, {
152
updateOnDuplicate: { skip: ["createdAt", "id"] }
153
});
154
155
// Save with relationships
156
const userWithPosts = new User();
157
userWithPosts.name = "David";
158
userWithPosts.posts = [
159
Object.assign(new Post(), { title: "First Post" }),
160
Object.assign(new Post(), { title: "Second Post" })
161
];
162
await save(userWithPosts);
163
```
164
165
### Delete Function
166
167
Deletes entities from the database with support for cascade deletion and bulk operations.
168
169
```typescript { .api }
170
/**
171
* Deletes entities from the database with support for cascade deletion
172
* @param object - Entity instance to delete
173
* @param opts - DeleteOptions including cascade deletion settings
174
* @returns Promise resolving to number of affected rows
175
*/
176
function remove<T>(object: any, opts?: DeleteOptions): Promise<number>;
177
178
/**
179
* Deletes entities by primary key with support for bulk deletion
180
* @param descriptor - Constructor class of the entity
181
* @param primaryId - Primary key value or array of values
182
* @param opts - DeleteOptions including cascade deletion settings
183
* @returns Promise resolving to number of affected rows
184
*/
185
function remove<T>(descriptor: ConstructorClass<T>, primaryId: number | Array<number>, opts?: DeleteOptions): Promise<number>;
186
187
interface DeleteOptions {
188
/** Enable cascade deletion of related entities */
189
deep?: boolean | Array<string>;
190
/** Database connection to use */
191
db?: DataBaseBase;
192
}
193
```
194
195
**Usage Examples:**
196
197
```typescript
198
import { remove, load } from "hibernatets";
199
200
// Delete single entity
201
const user = await load(User, 1);
202
const deletedRows = await remove(user);
203
204
// Delete by primary key
205
const deletedCount = await remove(User, 1);
206
207
// Delete multiple entities by IDs
208
const deletedCount = await remove(User, [1, 2, 3]);
209
210
// Cascade deletion of related entities
211
await remove(user, { deep: true });
212
213
// Selective cascade deletion
214
await remove(user, {
215
deep: ["posts", "profile"]
216
});
217
```
218
219
### Array Management
220
221
Functions for managing array relationships and bulk operations.
222
223
```typescript { .api }
224
/**
225
* Adds items to an array property with automatic relationship mapping
226
* @param parent - Parent entity containing the array
227
* @param key - Key of the array property
228
* @param opts - Array of items to add or AddArrayOpts object
229
*/
230
function addArrayItem<T extends ISaveAbleObject, K extends ArrayKeys<T>>(
231
parent: T,
232
key: K,
233
opts: Array<ArrayType<T, K> & ISaveAbleObject> | AddArrayOpts<ArrayType<T, K> & ISaveAbleObject>
234
): void;
235
236
interface AddArrayOpts<T> {
237
/** Database connection to use */
238
db: DataBaseBase;
239
/** Items to add to the array */
240
items: Array<T>;
241
}
242
243
interface ISaveAbleObject {
244
[key: string]: any;
245
}
246
247
type ArrayKeys<T> = {
248
[K in keyof T]: T[K] extends Array<infer U> ? K : never;
249
}[keyof T];
250
251
type ArrayType<T, K extends keyof T> = T[K] extends Array<infer U> ? U : never;
252
```
253
254
**Usage Examples:**
255
256
```typescript
257
import { addArrayItem, load, save } from "hibernatets";
258
259
// Load user with posts
260
const user = await load(User, 1, [], { deep: true });
261
262
// Add new posts to user
263
const newPosts = [
264
Object.assign(new Post(), { title: "New Post 1" }),
265
Object.assign(new Post(), { title: "New Post 2" })
266
];
267
268
addArrayItem(user, "posts", newPosts);
269
270
// Save to persist changes
271
await save(user);
272
```
273
274
### Query Execution
275
276
Execute pending database updates and retrieve results.
277
278
```typescript { .api }
279
/**
280
* Executes all pending database updates for an object and returns results
281
* @param object - Entity with pending updates
282
* @returns Promise resolving to array of result counts
283
*/
284
function queries(object: any): Promise<Array<number>>;
285
```
286
287
**Usage Examples:**
288
289
```typescript
290
import { queries, intercept } from "hibernatets";
291
292
// Enable automatic change tracking
293
const user = await load(User, 1);
294
intercept(user);
295
296
// Make changes
297
user.name = "Updated Name";
298
user.email = "updated@example.com";
299
300
// Execute all pending queries
301
const results = await queries(user);
302
console.log(`Updated ${results.length} database records`);
303
```
304
305
### Advanced Loading Patterns
306
307
Complex loading scenarios with conditional relationships and custom filters.
308
309
```typescript
310
import { load, SqlCondition, Mappings } from "hibernatets";
311
312
// Conditional deep loading based on user permissions
313
async function loadUserData(userId: number, includePrivateData: boolean) {
314
const loadOptions = {
315
deep: includePrivateData ? true : ["posts"],
316
skipFields: includePrivateData ? [] : ["email", "phone"]
317
};
318
319
return await load(User, userId, [], loadOptions);
320
}
321
322
// Load with complex relationship filters
323
const usersWithRecentPosts = await load(User, SqlCondition.ALL, [], {
324
deep: {
325
posts: new SqlCondition()
326
.column("createdAt")
327
.greater()
328
.param(new Date(Date.now() - 30 * 24 * 60 * 60 * 1000)) // Last 30 days
329
}
330
});
331
332
// Pagination with relationships
333
async function getPaginatedUsers(page: number, pageSize: number) {
334
const offset = page * pageSize;
335
336
return await load(User,
337
new SqlCondition()
338
.column("active")
339
.equals(true)
340
.and(c => c.column("id").greater().param(offset)),
341
[],
342
{
343
deep: ["profile"],
344
first: false
345
}
346
);
347
}
348
```
349
350
### Bulk Operations
351
352
Efficient patterns for handling large datasets and bulk operations.
353
354
```typescript
355
import { save, load, remove } from "hibernatets";
356
357
// Bulk insert with batch processing
358
async function bulkInsertUsers(userData: any[]) {
359
const batchSize = 100;
360
const results = [];
361
362
for (let i = 0; i < userData.length; i += batchSize) {
363
const batch = userData.slice(i, i + batchSize);
364
const users = batch.map(data => Object.assign(new User(), data));
365
const batchResults = await save(users);
366
results.push(...batchResults);
367
}
368
369
return results;
370
}
371
372
// Bulk update with selective fields
373
async function bulkUpdateUserStatus(userIds: number[], newStatus: boolean) {
374
const users = await load(User,
375
new SqlCondition().column("id").equals(userIds)
376
);
377
378
users.forEach(user => {
379
user.active = newStatus;
380
user.lastModified = new Date();
381
});
382
383
return await save(users, {
384
updateOnDuplicate: { skip: ["createdAt"] }
385
});
386
}
387
388
// Bulk delete with conditions
389
async function cleanupInactiveUsers(daysInactive: number) {
390
const cutoffDate = new Date(Date.now() - daysInactive * 24 * 60 * 60 * 1000);
391
392
const inactiveUsers = await load(User,
393
new SqlCondition()
394
.column("lastLoginAt")
395
.smaller()
396
.param(cutoffDate)
397
.and(c => c.column("active").equals(false))
398
);
399
400
const deletePromises = inactiveUsers.map(user =>
401
remove(user, { deep: ["posts", "profile"] })
402
);
403
404
return await Promise.all(deletePromises);
405
}
406
```