or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

active-record.mdbootstrap-config.mdcrud-operations.mddatabase-support.mdindex.mdpagination.mdquery-builder.mdrow-operations.mdservice-layer.mdupdate-chain.md

active-record.mddocs/

0

# Active Record Pattern

1

2

Entity-centric operations where domain objects handle their own persistence. The Active Record pattern provides a clean, object-oriented approach to database operations by embedding persistence logic directly into entity classes.

3

4

## Capabilities

5

6

### Model Base Class

7

8

Abstract base class that entities can extend to gain Active Record capabilities. Provides direct persistence methods on entity instances.

9

10

```java { .api }

11

/**

12

* Abstract base class for Active Record pattern implementation

13

* @param <T> Entity type extending Model

14

*/

15

public abstract class Model<T extends Model<T>> {

16

/**

17

* Save current entity (insert or update based on primary key)

18

* @return true if operation successful

19

*/

20

public boolean save();

21

22

/**

23

* Update current entity by primary key

24

* @return true if operation successful

25

*/

26

public boolean update();

27

28

/**

29

* Update current entity ignoring null fields

30

* @param ignoreNulls whether to ignore null values

31

* @return true if operation successful

32

*/

33

public boolean update(boolean ignoreNulls);

34

35

/**

36

* Delete current entity by primary key

37

* @return true if operation successful

38

*/

39

public boolean remove();

40

41

/**

42

* Save with Optional return type

43

* @return Optional<Boolean> with operation result

44

*/

45

public Optional<Boolean> saveOpt();

46

47

/**

48

* Update with Optional return type

49

* @return Optional<Boolean> with operation result

50

*/

51

public Optional<Boolean> updateOpt();

52

53

/**

54

* Delete with Optional return type

55

* @return Optional<Boolean> with operation result

56

*/

57

public Optional<Boolean> removeOpt();

58

}

59

```

60

61

**Basic Active Record Usage:**

62

63

```java

64

import com.mybatisflex.core.activerecord.Model;

65

import com.mybatisflex.annotation.Table;

66

import com.mybatisflex.annotation.Id;

67

68

// Entity with Active Record capabilities

69

@Table("users")

70

public class User extends Model<User> {

71

@Id

72

private Long id;

73

private String name;

74

private Integer age;

75

private String email;

76

private Boolean active;

77

78

// Constructors

79

public User() {}

80

81

public User(String name, Integer age, String email) {

82

this.name = name;

83

this.age = age;

84

this.email = email;

85

this.active = true;

86

}

87

88

// Getters and setters...

89

public Long getId() { return id; }

90

public void setId(Long id) { this.id = id; }

91

92

public String getName() { return name; }

93

public void setName(String name) { this.name = name; }

94

95

public Integer getAge() { return age; }

96

public void setAge(Integer age) { this.age = age; }

97

98

public String getEmail() { return email; }

99

public void setEmail(String email) { this.email = email; }

100

101

public Boolean getActive() { return active; }

102

public void setActive(Boolean active) { this.active = active; }

103

}

104

105

// Usage examples

106

public class UserActiveRecordExample {

107

public void demonstrateActiveRecord() {

108

// Create and save new user

109

User user = new User("Alice", 25, "alice@example.com");

110

boolean saved = user.save(); // INSERT operation

111

112

// Update existing user

113

user.setAge(26);

114

user.setEmail("alice.updated@example.com");

115

boolean updated = user.update(); // UPDATE operation

116

117

// Selective update (ignoring nulls)

118

User partialUpdate = new User();

119

partialUpdate.setId(user.getId());

120

partialUpdate.setAge(27); // Only age will be updated

121

partialUpdate.update(true); // ignoreNulls = true

122

123

// Delete user

124

boolean deleted = user.remove(); // DELETE operation

125

}

126

}

127

```

128

129

### MapperModel Base Class

130

131

Enhanced Active Record class that provides direct access to mapper functionality for more advanced operations.

132

133

```java { .api }

134

/**

135

* Enhanced Active Record with mapper access

136

* @param <T> Entity type extending MapperModel

137

*/

138

public abstract class MapperModel<T extends MapperModel<T>> extends Model<T> {

139

/**

140

* Get the mapper instance for this entity type

141

* @return BaseMapper instance

142

*/

143

protected BaseMapper<T> getMapper();

144

145

/**

146

* Perform query operations on this entity type

147

* @return QueryWrapper for building queries

148

*/

149

public static QueryWrapper query();

150

151

/**

152

* Find entity by primary key

153

* @param id primary key value

154

* @return entity instance or null

155

*/

156

public static <T extends MapperModel<T>> T findById(Serializable id);

157

158

/**

159

* Find all entities of this type

160

* @return list of all entities

161

*/

162

public static <T extends MapperModel<T>> List<T> findAll();

163

164

/**

165

* Count all entities of this type

166

* @return total count

167

*/

168

public static <T extends MapperModel<T>> long count();

169

}

170

```

171

172

**MapperModel Usage:**

173

174

```java

175

@Table("users")

176

public class User extends MapperModel<User> {

177

@Id

178

private Long id;

179

private String name;

180

private Integer age;

181

private String email;

182

183

// Constructors, getters, setters...

184

}

185

186

// Usage with enhanced capabilities

187

public class UserMapperModelExample {

188

public void demonstrateMapperModel() {

189

// Static query methods

190

User user = User.findById(1L);

191

List<User> allUsers = User.findAll();

192

long totalUsers = User.count();

193

194

// Custom queries using static method

195

List<User> adults = User.query()

196

.select()

197

.from(User.class)

198

.where(USER.AGE.ge(18))

199

.list(); // Custom method that executes query

200

201

// Direct mapper access for advanced operations

202

User user = new User("Bob", 30, "bob@example.com");

203

BaseMapper<User> mapper = user.getMapper();

204

205

// Use mapper for batch operations

206

List<User> users = Arrays.asList(

207

new User("Charlie", 28, "charlie@example.com"),

208

new User("Diana", 32, "diana@example.com")

209

);

210

mapper.insertBatch(users);

211

}

212

}

213

```

214

215

### Field Query Operations

216

217

Query building focused on specific fields with the Active Record pattern.

218

219

```java { .api }

220

/**

221

* Field-specific query operations for Active Record

222

*/

223

public abstract class Model<T extends Model<T>> {

224

/**

225

* Create query for specific fields of this entity

226

* @param fields field names to query

227

* @return FieldsQuery instance

228

*/

229

public FieldsQuery<T> withFields(String... fields);

230

231

/**

232

* Create query including relationship loading

233

* @param relations relationship field names

234

* @return RelationsQuery instance

235

*/

236

public RelationsQuery<T> withRelations(String... relations);

237

}

238

239

/**

240

* Query builder for field-specific operations

241

* @param <T> Entity type

242

*/

243

public class FieldsQuery<T> {

244

/**

245

* Add WHERE conditions

246

* @param condition query condition

247

* @return FieldsQuery for chaining

248

*/

249

public FieldsQuery<T> where(QueryCondition condition);

250

251

/**

252

* Execute query and return single result

253

* @return single entity or null

254

*/

255

public T one();

256

257

/**

258

* Execute query and return list of results

259

* @return list of entities

260

*/

261

public List<T> list();

262

263

/**

264

* Execute query with pagination

265

* @param page pagination parameters

266

* @return page of results

267

*/

268

public Page<T> page(Page<T> page);

269

}

270

271

/**

272

* Query builder for relationship loading

273

* @param <T> Entity type

274

*/

275

public class RelationsQuery<T> {

276

/**

277

* Add WHERE conditions

278

* @param condition query condition

279

* @return RelationsQuery for chaining

280

*/

281

public RelationsQuery<T> where(QueryCondition condition);

282

283

/**

284

* Execute query and return single result with relations

285

* @return single entity with loaded relations or null

286

*/

287

public T one();

288

289

/**

290

* Execute query and return list with relations

291

* @return list of entities with loaded relations

292

*/

293

public List<T> list();

294

}

295

```

296

297

**Field Query Examples:**

298

299

```java

300

// Field-specific queries

301

User user = new User()

302

.withFields("name", "email")

303

.where(USER.AGE.ge(18))

304

.one();

305

306

List<User> users = new User()

307

.withFields("id", "name", "age")

308

.where(USER.ACTIVE.eq(true))

309

.list();

310

311

// Relationship loading

312

User userWithOrders = new User()

313

.withRelations("orders", "profile")

314

.where(USER.ID.eq(1L))

315

.one();

316

317

List<User> usersWithProfiles = new User()

318

.withRelations("profile")

319

.where(USER.CITY.eq("New York"))

320

.list();

321

```

322

323

### Transaction Support

324

325

Active Record operations with transaction management.

326

327

```java { .api }

328

/**

329

* Transaction support for Active Record operations

330

*/

331

public abstract class Model<T extends Model<T>> {

332

/**

333

* Execute operation within transaction

334

* @param operation operation to execute

335

* @return operation result

336

*/

337

public static <R> R transaction(Supplier<R> operation);

338

339

/**

340

* Execute operation within transaction (void return)

341

* @param operation operation to execute

342

*/

343

public static void transaction(Runnable operation);

344

345

/**

346

* Execute operation within transaction with specific isolation level

347

* @param isolationLevel transaction isolation level

348

* @param operation operation to execute

349

* @return operation result

350

*/

351

public static <R> R transaction(TransactionIsolationLevel isolationLevel, Supplier<R> operation);

352

}

353

```

354

355

**Transaction Examples:**

356

357

```java

358

// Simple transaction

359

boolean result = User.transaction(() -> {

360

User user1 = new User("Alice", 25, "alice@example.com");

361

User user2 = new User("Bob", 30, "bob@example.com");

362

363

return user1.save() && user2.save();

364

});

365

366

// Void transaction

367

User.transaction(() -> {

368

User user = User.findById(1L);

369

user.setAge(user.getAge() + 1);

370

user.update();

371

372

// Create audit log

373

AuditLog log = new AuditLog("User age updated", user.getId());

374

log.save();

375

});

376

377

// Transaction with isolation level

378

User result = User.transaction(TransactionIsolationLevel.READ_COMMITTED, () -> {

379

User user = User.findById(1L);

380

user.setLastLoginTime(new Date());

381

user.update();

382

return user;

383

});

384

```

385

386

## Types

387

388

```java { .api }

389

// Active Record base types

390

public interface Serializable {

391

// Marker interface for primary key types

392

}

393

394

// Query result types

395

public class FieldsQuery<T> {

396

public FieldsQuery<T> where(QueryCondition condition);

397

public T one();

398

public List<T> list();

399

public Page<T> page(Page<T> page);

400

}

401

402

public class RelationsQuery<T> {

403

public RelationsQuery<T> where(QueryCondition condition);

404

public T one();

405

public List<T> list();

406

}

407

408

// Transaction types

409

public enum TransactionIsolationLevel {

410

READ_UNCOMMITTED,

411

READ_COMMITTED,

412

REPEATABLE_READ,

413

SERIALIZABLE

414

}

415

416

// Functional interfaces for transactions

417

@FunctionalInterface

418

public interface Supplier<T> {

419

T get();

420

}

421

422

@FunctionalInterface

423

public interface Runnable {

424

void run();

425

}

426

```