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
```