or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

configuration.mddata-operations.mddatabase-adapters.mdentity-modeling.mdindex.mdsql-conditions.md

data-operations.mddocs/

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

```