0
# Static Database Utilities
1
2
MyBatis-Plus Extension provides the `Db` utility class that offers static methods for direct database operations without requiring service layer dependency injection. This is particularly useful in utility classes, static contexts, or when you need database operations outside of the traditional service layer.
3
4
## Core Components
5
6
### Db Utility Class
7
8
The main static utility class providing all common database operations.
9
10
```java { .api }
11
public class Db {
12
13
// Save operations
14
public static <T> boolean save(T entity);
15
public static <T> boolean saveBatch(Collection<T> entityList);
16
public static <T> boolean saveBatch(Collection<T> entityList, int batchSize);
17
public static <T> boolean saveOrUpdate(T entity);
18
public static <T> boolean saveOrUpdateBatch(Collection<T> entityList);
19
public static <T> boolean saveOrUpdateBatch(Collection<T> entityList, int batchSize);
20
21
// Remove operations
22
public static <T> boolean removeById(Object entity);
23
public static <T> boolean removeById(Class<T> entityClass, Serializable id);
24
public static <T> boolean removeByIds(Class<T> entityClass, Collection<? extends Serializable> list);
25
public static <T> boolean removeByMap(Class<T> entityClass, Map<String, Object> map);
26
public static <T> boolean remove(Class<T> entityClass, Wrapper<T> queryWrapper);
27
28
// Update operations
29
public static <T> boolean updateById(T entity);
30
public static <T> boolean update(Class<T> entityClass, Wrapper<T> updateWrapper);
31
public static <T> boolean update(Class<T> entityClass, T entity, Wrapper<T> updateWrapper);
32
public static <T> boolean updateBatchById(Collection<T> entityList);
33
public static <T> boolean updateBatchById(Collection<T> entityList, int batchSize);
34
35
// Query operations
36
public static <T> T getById(Class<T> entityClass, Serializable id);
37
public static <T> T getOne(Class<T> entityClass, Wrapper<T> queryWrapper);
38
public static <T> T getOne(Class<T> entityClass, Wrapper<T> queryWrapper, boolean throwEx);
39
public static <T> Optional<T> getOptById(Class<T> entityClass, Serializable id);
40
public static <T> Optional<T> getOneOpt(Class<T> entityClass, Wrapper<T> queryWrapper);
41
public static <T> Optional<T> getOneOpt(Class<T> entityClass, Wrapper<T> queryWrapper, boolean throwEx);
42
public static <T> Map<String, Object> getMap(Class<T> entityClass, Wrapper<T> queryWrapper);
43
public static <T, V> V getObj(Class<T> entityClass, Wrapper<T> queryWrapper, Function<? super Object, V> mapper);
44
45
// List operations
46
public static <T> List<T> list(Class<T> entityClass);
47
public static <T> List<T> list(Class<T> entityClass, Wrapper<T> queryWrapper);
48
public static <T> List<T> listByIds(Class<T> entityClass, Collection<? extends Serializable> idList);
49
public static <T> List<T> listByMap(Class<T> entityClass, Map<String, Object> columnMap);
50
public static <T> List<Map<String, Object>> listMaps(Class<T> entityClass);
51
public static <T> List<Map<String, Object>> listMaps(Class<T> entityClass, Wrapper<T> queryWrapper);
52
public static <T, V> List<V> listObjs(Class<T> entityClass);
53
public static <T, V> List<V> listObjs(Class<T> entityClass, Function<? super Object, V> mapper);
54
public static <T, V> List<V> listObjs(Class<T> entityClass, Wrapper<T> queryWrapper);
55
public static <T, V> List<V> listObjs(Class<T> entityClass, Wrapper<T> queryWrapper, Function<? super Object, V> mapper);
56
57
// Count operations
58
public static <T> long count(Class<T> entityClass);
59
public static <T> long count(Class<T> entityClass, Wrapper<T> queryWrapper);
60
public static <T> boolean exists(Class<T> entityClass, Wrapper<T> queryWrapper);
61
62
// Pagination operations
63
public static <T> Page<T> page(Class<T> entityClass, IPage<T> page);
64
public static <T> Page<T> page(Class<T> entityClass, IPage<T> page, Wrapper<T> queryWrapper);
65
public static <T> Page<Map<String, Object>> pageMaps(Class<T> entityClass, IPage<T> page, Wrapper<T> queryWrapper);
66
67
// Chain operations
68
public static <T> QueryChainWrapper<T> query(Class<T> entityClass);
69
public static <T> LambdaQueryChainWrapper<T> lambdaQuery(Class<T> entityClass);
70
public static <T> KtQueryChainWrapper<T> ktQuery(Class<T> entityClass);
71
public static <T> UpdateChainWrapper<T> update(Class<T> entityClass);
72
public static <T> LambdaUpdateChainWrapper<T> lambdaUpdate(Class<T> entityClass);
73
public static <T> KtUpdateChainWrapper<T> ktUpdate(Class<T> entityClass);
74
}
75
```
76
77
### ChainWrappers Factory
78
79
Factory class for creating chain wrappers directly with mappers or entity classes.
80
81
```java { .api }
82
public class ChainWrappers {
83
84
// Query chain factory methods
85
public static <T> QueryChainWrapper<T> queryChain(BaseMapper<T> baseMapper);
86
public static <T> QueryChainWrapper<T> queryChain(Class<T> entityClass);
87
public static <T> LambdaQueryChainWrapper<T> lambdaQueryChain(BaseMapper<T> baseMapper);
88
public static <T> LambdaQueryChainWrapper<T> lambdaQueryChain(Class<T> entityClass);
89
public static <T> KtQueryChainWrapper<T> ktQueryChain(BaseMapper<T> baseMapper);
90
public static <T> KtQueryChainWrapper<T> ktQueryChain(Class<T> entityClass);
91
92
// Update chain factory methods
93
public static <T> UpdateChainWrapper<T> updateChain(BaseMapper<T> baseMapper);
94
public static <T> UpdateChainWrapper<T> updateChain(Class<T> entityClass);
95
public static <T> LambdaUpdateChainWrapper<T> lambdaUpdateChain(BaseMapper<T> baseMapper);
96
public static <T> LambdaUpdateChainWrapper<T> lambdaUpdateChain(Class<T> entityClass);
97
public static <T> KtUpdateChainWrapper<T> ktUpdateChain(BaseMapper<T> baseMapper);
98
public static <T> KtUpdateChainWrapper<T> ktUpdateChain(Class<T> entityClass);
99
}
100
```
101
102
## Usage Examples
103
104
### Basic Save Operations
105
106
```java
107
// Save single entity
108
User user = new User("John Doe", "john@example.com");
109
boolean saved = Db.save(user);
110
111
if (saved) {
112
System.out.println("User saved with ID: " + user.getId());
113
}
114
115
// Save batch
116
List<User> users = Arrays.asList(
117
new User("Alice", "alice@example.com"),
118
new User("Bob", "bob@example.com"),
119
new User("Charlie", "charlie@example.com")
120
);
121
boolean allSaved = Db.saveBatch(users);
122
123
// Save batch with custom batch size
124
boolean saved = Db.saveBatch(users, 50);
125
126
// Save or update
127
User existingUser = Db.getById(User.class, 1L);
128
if (existingUser != null) {
129
existingUser.setEmail("newemail@example.com");
130
boolean updated = Db.saveOrUpdate(existingUser);
131
}
132
```
133
134
### Query Operations
135
136
```java
137
// Get by ID
138
User user = Db.getById(User.class, 1L);
139
if (user != null) {
140
System.out.println("Found user: " + user.getName());
141
}
142
143
// Get with Optional
144
Optional<User> optionalUser = Db.getOptById(User.class, 1L);
145
optionalUser.ifPresent(u -> System.out.println("User: " + u.getName()));
146
147
// Get single with conditions
148
User activeUser = Db.getOne(User.class,
149
new QueryWrapper<User>().eq("active", true).eq("email", "john@example.com"));
150
151
// Get single with Optional
152
Optional<User> optUser = Db.getOneOpt(User.class,
153
new QueryWrapper<User>().eq("email", "unique@example.com"));
154
155
// List all
156
List<User> allUsers = Db.list(User.class);
157
158
// List with conditions
159
List<User> activeUsers = Db.list(User.class,
160
new QueryWrapper<User>().eq("active", true));
161
162
// List by IDs
163
List<User> specificUsers = Db.listByIds(User.class, Arrays.asList(1L, 2L, 3L));
164
165
// List by column map
166
Map<String, Object> conditions = new HashMap<>();
167
conditions.put("active", true);
168
conditions.put("age", 30);
169
List<User> users = Db.listByMap(User.class, conditions);
170
```
171
172
### Count and Existence
173
174
```java
175
// Count all
176
long totalUsers = Db.count(User.class);
177
System.out.println("Total users: " + totalUsers);
178
179
// Count with conditions
180
long activeUsers = Db.count(User.class,
181
new QueryWrapper<User>().eq("active", true));
182
183
long adultUsers = Db.count(User.class,
184
new QueryWrapper<User>().ge("age", 18));
185
186
// Check existence
187
boolean hasActiveUsers = Db.exists(User.class,
188
new QueryWrapper<User>().eq("active", true));
189
190
if (hasActiveUsers) {
191
System.out.println("Active users exist");
192
}
193
```
194
195
### Update Operations
196
197
```java
198
// Update by ID
199
User user = Db.getById(User.class, 1L);
200
if (user != null) {
201
user.setEmail("updated@example.com");
202
user.setUpdatedTime(LocalDateTime.now());
203
boolean updated = Db.updateById(user);
204
}
205
206
// Update with conditions (using wrapper only)
207
boolean updated = Db.update(User.class,
208
new UpdateWrapper<User>()
209
.set("active", false)
210
.set("updated_time", LocalDateTime.now())
211
.eq("last_login", null)
212
);
213
214
// Update with entity and conditions
215
User updateEntity = new User();
216
updateEntity.setActive(false);
217
boolean updated = Db.update(User.class, updateEntity,
218
new UpdateWrapper<User>().gt("age", 65));
219
220
// Batch update by IDs
221
List<User> usersToUpdate = Db.listByIds(User.class, Arrays.asList(1L, 2L, 3L));
222
usersToUpdate.forEach(user -> user.setActive(true));
223
boolean allUpdated = Db.updateBatchById(usersToUpdate);
224
```
225
226
### Remove Operations
227
228
```java
229
// Remove by entity (uses entity's ID)
230
User user = Db.getById(User.class, 1L);
231
boolean removed = Db.removeById(user);
232
233
// Remove by class and ID
234
boolean removed = Db.removeById(User.class, 1L);
235
236
// Remove by IDs
237
boolean removed = Db.removeByIds(User.class, Arrays.asList(1L, 2L, 3L));
238
239
// Remove by column map
240
Map<String, Object> conditions = new HashMap<>();
241
conditions.put("active", false);
242
conditions.put("last_login", null);
243
boolean removed = Db.removeByMap(User.class, conditions);
244
245
// Remove with conditions
246
boolean removed = Db.remove(User.class,
247
new QueryWrapper<User>()
248
.eq("active", false)
249
.lt("created_time", LocalDateTime.now().minusYears(1))
250
);
251
```
252
253
### Pagination with Static Methods
254
255
```java
256
// Basic pagination
257
Page<User> page = new Page<>(1, 10);
258
Page<User> result = Db.page(User.class, page);
259
260
List<User> users = result.getRecords();
261
long total = result.getTotal();
262
263
// Pagination with conditions
264
Page<User> conditionPage = Db.page(User.class, new Page<>(1, 15),
265
new QueryWrapper<User>().eq("active", true).orderByDesc("created_time"));
266
267
// Paginate map results
268
Page<Map<String, Object>> mapPage = Db.pageMaps(User.class, new Page<>(1, 10),
269
new QueryWrapper<User>().select("id", "name", "email"));
270
```
271
272
### Object Mapping and Maps
273
274
```java
275
// Get as map
276
Map<String, Object> userMap = Db.getMap(User.class,
277
new QueryWrapper<User>().eq("id", 1L));
278
279
// List as maps
280
List<Map<String, Object>> userMaps = Db.listMaps(User.class,
281
new QueryWrapper<User>().eq("active", true));
282
283
// List specific objects
284
List<String> emails = Db.listObjs(User.class,
285
new QueryWrapper<User>().select("email").eq("active", true),
286
Object::toString);
287
288
// List all emails
289
List<String> allEmails = Db.listObjs(User.class, Object::toString);
290
```
291
292
### Chain Operations with Static Methods
293
294
```java
295
// Query chains
296
List<User> activeUsers = Db.query(User.class)
297
.eq("active", true)
298
.gt("age", 18)
299
.orderByDesc("created_time")
300
.list();
301
302
User user = Db.lambdaQuery(User.class)
303
.eq(User::getActive, true)
304
.eq(User::getEmail, "john@example.com")
305
.one();
306
307
// Update chains
308
boolean updated = Db.update(User.class)
309
.set("last_login", LocalDateTime.now())
310
.eq("id", 1L)
311
.update();
312
313
boolean deactivated = Db.lambdaUpdate(User.class)
314
.set(User::getActive, false)
315
.isNull(User::getLastLogin)
316
.update();
317
318
// Remove with chains
319
boolean removed = Db.update(User.class)
320
.eq("active", false)
321
.lt("created_time", LocalDateTime.now().minusMonths(6))
322
.remove();
323
```
324
325
### ChainWrappers Factory Usage
326
327
```java
328
// Using ChainWrappers with entity class
329
List<User> users = ChainWrappers.queryChain(User.class)
330
.eq("department", "IT")
331
.isNotNull("email")
332
.orderByAsc("name")
333
.list();
334
335
boolean updated = ChainWrappers.updateChain(User.class)
336
.set("department", "Engineering")
337
.eq("department", "IT")
338
.update();
339
340
// Lambda chains with ChainWrappers
341
List<User> managers = ChainWrappers.lambdaQueryChain(User.class)
342
.eq(User::getRole, "MANAGER")
343
.isNotNull(User::getTeamId)
344
.orderByDesc(User::getCreatedTime)
345
.list();
346
347
boolean updated = ChainWrappers.lambdaUpdateChain(User.class)
348
.set(User::getStatus, "ACTIVE")
349
.eq(User::getRole, "USER")
350
.update();
351
```
352
353
## Advanced Usage Patterns
354
355
### Utility Class Implementation
356
357
```java
358
public class UserUtils {
359
360
// Static utility methods using Db class
361
public static List<User> findActiveUsersByDepartment(String department) {
362
return Db.list(User.class,
363
new QueryWrapper<User>()
364
.eq("active", true)
365
.eq("department", department)
366
.orderByAsc("name")
367
);
368
}
369
370
public static boolean deactivateInactiveUsers(int inactiveDays) {
371
LocalDateTime cutoffDate = LocalDateTime.now().minusDays(inactiveDays);
372
return Db.update(User.class,
373
new UpdateWrapper<User>()
374
.set("active", false)
375
.set("deactivated_time", LocalDateTime.now())
376
.lt("last_login", cutoffDate)
377
.eq("active", true)
378
);
379
}
380
381
public static long countUsersByRole(String role) {
382
return Db.count(User.class,
383
new QueryWrapper<User>().eq("role", role).eq("active", true)
384
);
385
}
386
387
public static Page<User> searchUsers(String keyword, int page, int size) {
388
return Db.page(User.class, new Page<>(page, size),
389
new QueryWrapper<User>()
390
.and(wrapper -> wrapper
391
.like("name", keyword)
392
.or()
393
.like("email", keyword)
394
)
395
.eq("active", true)
396
.orderByDesc("created_time")
397
);
398
}
399
400
public static boolean bulkUpdateUserStatus(List<Long> userIds, String status) {
401
return Db.update(User.class,
402
new UpdateWrapper<User>()
403
.set("status", status)
404
.set("updated_time", LocalDateTime.now())
405
.in("id", userIds)
406
);
407
}
408
409
public static void cleanupOldInactiveUsers() {
410
LocalDateTime cutoffDate = LocalDateTime.now().minusYears(2);
411
Db.remove(User.class,
412
new QueryWrapper<User>()
413
.eq("active", false)
414
.lt("deactivated_time", cutoffDate)
415
);
416
}
417
}
418
```
419
420
### Scheduled Tasks
421
422
```java
423
@Component
424
public class UserMaintenanceScheduler {
425
426
@Scheduled(cron = "0 0 2 * * ?") // Daily at 2 AM
427
public void deactivateInactiveUsers() {
428
// Deactivate users inactive for 90 days
429
LocalDateTime cutoffDate = LocalDateTime.now().minusDays(90);
430
431
long count = Db.update(User.class,
432
new UpdateWrapper<User>()
433
.set("active", false)
434
.set("deactivated_time", LocalDateTime.now())
435
.lt("last_login", cutoffDate)
436
.eq("active", true)
437
) ? 1 : 0;
438
439
if (count > 0) {
440
System.out.println("Deactivated inactive users");
441
}
442
}
443
444
@Scheduled(cron = "0 0 3 * * 0") // Weekly on Sunday at 3 AM
445
public void cleanupOldData() {
446
// Remove users inactive for over 2 years
447
LocalDateTime cutoffDate = LocalDateTime.now().minusYears(2);
448
449
boolean removed = Db.remove(User.class,
450
new QueryWrapper<User>()
451
.eq("active", false)
452
.lt("deactivated_time", cutoffDate)
453
);
454
455
if (removed) {
456
System.out.println("Cleaned up old inactive user data");
457
}
458
}
459
}
460
```
461
462
### Data Migration Utilities
463
464
```java
465
public class DataMigrationUtils {
466
467
public static void migrateUserRoles() {
468
// Update old role format to new format
469
Db.update(User.class,
470
new UpdateWrapper<User>()
471
.set("role", "ADMIN")
472
.eq("role", "admin")
473
);
474
475
Db.update(User.class,
476
new UpdateWrapper<User>()
477
.setSql("role = UPPER(role)")
478
.ne("role", "ADMIN")
479
);
480
}
481
482
public static void addDefaultValues() {
483
// Add default values for users missing certain fields
484
Db.update(User.class,
485
new UpdateWrapper<User>()
486
.set("status", "ACTIVE")
487
.isNull("status")
488
);
489
490
Db.update(User.class,
491
new UpdateWrapper<User>()
492
.set("created_time", LocalDateTime.now())
493
.isNull("created_time")
494
);
495
}
496
497
public static void normalizeEmailAddresses() {
498
// Normalize email addresses to lowercase
499
List<User> users = Db.list(User.class,
500
new QueryWrapper<User>().isNotNull("email")
501
);
502
503
List<User> toUpdate = users.stream()
504
.filter(user -> !user.getEmail().equals(user.getEmail().toLowerCase()))
505
.peek(user -> user.setEmail(user.getEmail().toLowerCase()))
506
.collect(Collectors.toList());
507
508
if (!toUpdate.isEmpty()) {
509
Db.updateBatchById(toUpdate);
510
}
511
}
512
}
513
```
514
515
### Configuration and Cache Integration
516
517
```java
518
@Component
519
public class UserCacheManager {
520
521
@Cacheable(value = "users", key = "#id")
522
public User getCachedUser(Long id) {
523
return Db.getById(User.class, id);
524
}
525
526
@CacheEvict(value = "users", key = "#user.id")
527
public boolean updateUserWithCacheEviction(User user) {
528
return Db.updateById(user);
529
}
530
531
@CacheEvict(value = "users", allEntries = true)
532
public void clearUserCache() {
533
// Cache will be cleared after method execution
534
}
535
536
public List<User> getActiveUsersWithCache() {
537
// Check cache first, then database
538
return Db.list(User.class,
539
new QueryWrapper<User>().eq("active", true)
540
);
541
}
542
}
543
```
544
545
## Best Practices
546
547
### 1. Error Handling
548
549
```java
550
public class SafeDbOperations {
551
552
public static Optional<User> safeGetById(Long id) {
553
try {
554
return Db.getOptById(User.class, id);
555
} catch (Exception e) {
556
System.err.println("Error fetching user by ID " + id + ": " + e.getMessage());
557
return Optional.empty();
558
}
559
}
560
561
public static boolean safeSave(User user) {
562
try {
563
return Db.save(user);
564
} catch (Exception e) {
565
System.err.println("Error saving user: " + e.getMessage());
566
return false;
567
}
568
}
569
}
570
```
571
572
### 2. Parameter Validation
573
574
```java
575
public class ValidatedDbOperations {
576
577
public static List<User> findUsersByIds(Collection<Long> ids) {
578
if (ids == null || ids.isEmpty()) {
579
return Collections.emptyList();
580
}
581
582
return Db.listByIds(User.class, ids);
583
}
584
585
public static long countActiveUsers() {
586
return Db.count(User.class,
587
new QueryWrapper<User>().eq("active", true)
588
);
589
}
590
}
591
```
592
593
### 3. Performance Considerations
594
595
```java
596
public class PerformantDbOperations {
597
598
// Use batch operations for multiple records
599
public static boolean saveUsers(List<User> users) {
600
if (users.size() > 100) {
601
return Db.saveBatch(users, 50); // Custom batch size
602
} else {
603
return Db.saveBatch(users);
604
}
605
}
606
607
// Use specific field selection when possible
608
public static List<String> getUserEmails() {
609
return Db.listObjs(User.class,
610
new QueryWrapper<User>()
611
.select("email")
612
.eq("active", true),
613
Object::toString
614
);
615
}
616
617
// Use pagination for large result sets
618
public static Page<User> getLargeUserSet(int page, int size) {
619
return Db.page(User.class,
620
new Page<User>(page, size).setOptimizeCountSql(true)
621
);
622
}
623
}
624
```
625
626
The static utility approach is particularly useful for:
627
- Utility classes and helper methods
628
- Scheduled tasks and background jobs
629
- Data migration scripts
630
- Static initialization blocks
631
- Testing scenarios where dependency injection is not available
632
- Simple CRUD operations without complex business logic