CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/maven-com-baomidou--mybatis-plus-extension

MyBatis-Plus Extension module providing advanced features including service layers, Kotlin extensions, SQL parsers, caching mechanisms, and various interceptors for enhanced ORM functionality

Pending
Overview
Eval results
Files

static-utilities.mddocs/

Static Database Utilities

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.

Core Components

Db Utility Class

The main static utility class providing all common database operations.

public class Db {
    
    // Save operations
    public static <T> boolean save(T entity);
    public static <T> boolean saveBatch(Collection<T> entityList);
    public static <T> boolean saveBatch(Collection<T> entityList, int batchSize);
    public static <T> boolean saveOrUpdate(T entity);
    public static <T> boolean saveOrUpdateBatch(Collection<T> entityList);
    public static <T> boolean saveOrUpdateBatch(Collection<T> entityList, int batchSize);
    
    // Remove operations
    public static <T> boolean removeById(Object entity);
    public static <T> boolean removeById(Class<T> entityClass, Serializable id);
    public static <T> boolean removeByIds(Class<T> entityClass, Collection<? extends Serializable> list);
    public static <T> boolean removeByMap(Class<T> entityClass, Map<String, Object> map);
    public static <T> boolean remove(Class<T> entityClass, Wrapper<T> queryWrapper);
    
    // Update operations
    public static <T> boolean updateById(T entity);
    public static <T> boolean update(Class<T> entityClass, Wrapper<T> updateWrapper);
    public static <T> boolean update(Class<T> entityClass, T entity, Wrapper<T> updateWrapper);
    public static <T> boolean updateBatchById(Collection<T> entityList);
    public static <T> boolean updateBatchById(Collection<T> entityList, int batchSize);
    
    // Query operations
    public static <T> T getById(Class<T> entityClass, Serializable id);
    public static <T> T getOne(Class<T> entityClass, Wrapper<T> queryWrapper);
    public static <T> T getOne(Class<T> entityClass, Wrapper<T> queryWrapper, boolean throwEx);
    public static <T> Optional<T> getOptById(Class<T> entityClass, Serializable id);
    public static <T> Optional<T> getOneOpt(Class<T> entityClass, Wrapper<T> queryWrapper);
    public static <T> Optional<T> getOneOpt(Class<T> entityClass, Wrapper<T> queryWrapper, boolean throwEx);
    public static <T> Map<String, Object> getMap(Class<T> entityClass, Wrapper<T> queryWrapper);
    public static <T, V> V getObj(Class<T> entityClass, Wrapper<T> queryWrapper, Function<? super Object, V> mapper);
    
    // List operations
    public static <T> List<T> list(Class<T> entityClass);
    public static <T> List<T> list(Class<T> entityClass, Wrapper<T> queryWrapper);
    public static <T> List<T> listByIds(Class<T> entityClass, Collection<? extends Serializable> idList);
    public static <T> List<T> listByMap(Class<T> entityClass, Map<String, Object> columnMap);
    public static <T> List<Map<String, Object>> listMaps(Class<T> entityClass);
    public static <T> List<Map<String, Object>> listMaps(Class<T> entityClass, Wrapper<T> queryWrapper);
    public static <T, V> List<V> listObjs(Class<T> entityClass);
    public static <T, V> List<V> listObjs(Class<T> entityClass, Function<? super Object, V> mapper);
    public static <T, V> List<V> listObjs(Class<T> entityClass, Wrapper<T> queryWrapper);
    public static <T, V> List<V> listObjs(Class<T> entityClass, Wrapper<T> queryWrapper, Function<? super Object, V> mapper);
    
    // Count operations
    public static <T> long count(Class<T> entityClass);
    public static <T> long count(Class<T> entityClass, Wrapper<T> queryWrapper);
    public static <T> boolean exists(Class<T> entityClass, Wrapper<T> queryWrapper);
    
    // Pagination operations
    public static <T> Page<T> page(Class<T> entityClass, IPage<T> page);
    public static <T> Page<T> page(Class<T> entityClass, IPage<T> page, Wrapper<T> queryWrapper);
    public static <T> Page<Map<String, Object>> pageMaps(Class<T> entityClass, IPage<T> page, Wrapper<T> queryWrapper);
    
    // Chain operations
    public static <T> QueryChainWrapper<T> query(Class<T> entityClass);
    public static <T> LambdaQueryChainWrapper<T> lambdaQuery(Class<T> entityClass);
    public static <T> KtQueryChainWrapper<T> ktQuery(Class<T> entityClass);
    public static <T> UpdateChainWrapper<T> update(Class<T> entityClass);
    public static <T> LambdaUpdateChainWrapper<T> lambdaUpdate(Class<T> entityClass);
    public static <T> KtUpdateChainWrapper<T> ktUpdate(Class<T> entityClass);
}

ChainWrappers Factory

Factory class for creating chain wrappers directly with mappers or entity classes.

public class ChainWrappers {
    
    // Query chain factory methods
    public static <T> QueryChainWrapper<T> queryChain(BaseMapper<T> baseMapper);
    public static <T> QueryChainWrapper<T> queryChain(Class<T> entityClass);
    public static <T> LambdaQueryChainWrapper<T> lambdaQueryChain(BaseMapper<T> baseMapper);
    public static <T> LambdaQueryChainWrapper<T> lambdaQueryChain(Class<T> entityClass);
    public static <T> KtQueryChainWrapper<T> ktQueryChain(BaseMapper<T> baseMapper);
    public static <T> KtQueryChainWrapper<T> ktQueryChain(Class<T> entityClass);
    
    // Update chain factory methods
    public static <T> UpdateChainWrapper<T> updateChain(BaseMapper<T> baseMapper);
    public static <T> UpdateChainWrapper<T> updateChain(Class<T> entityClass);
    public static <T> LambdaUpdateChainWrapper<T> lambdaUpdateChain(BaseMapper<T> baseMapper);
    public static <T> LambdaUpdateChainWrapper<T> lambdaUpdateChain(Class<T> entityClass);
    public static <T> KtUpdateChainWrapper<T> ktUpdateChain(BaseMapper<T> baseMapper);
    public static <T> KtUpdateChainWrapper<T> ktUpdateChain(Class<T> entityClass);
}

Usage Examples

Basic Save Operations

// Save single entity
User user = new User("John Doe", "john@example.com");
boolean saved = Db.save(user);

if (saved) {
    System.out.println("User saved with ID: " + user.getId());
}

// Save batch
List<User> users = Arrays.asList(
    new User("Alice", "alice@example.com"),
    new User("Bob", "bob@example.com"),
    new User("Charlie", "charlie@example.com")
);
boolean allSaved = Db.saveBatch(users);

// Save batch with custom batch size
boolean saved = Db.saveBatch(users, 50);

// Save or update
User existingUser = Db.getById(User.class, 1L);
if (existingUser != null) {
    existingUser.setEmail("newemail@example.com");
    boolean updated = Db.saveOrUpdate(existingUser);
}

Query Operations

// Get by ID
User user = Db.getById(User.class, 1L);
if (user != null) {
    System.out.println("Found user: " + user.getName());
}

// Get with Optional
Optional<User> optionalUser = Db.getOptById(User.class, 1L);
optionalUser.ifPresent(u -> System.out.println("User: " + u.getName()));

// Get single with conditions
User activeUser = Db.getOne(User.class, 
    new QueryWrapper<User>().eq("active", true).eq("email", "john@example.com"));

// Get single with Optional
Optional<User> optUser = Db.getOneOpt(User.class,
    new QueryWrapper<User>().eq("email", "unique@example.com"));

// List all
List<User> allUsers = Db.list(User.class);

// List with conditions
List<User> activeUsers = Db.list(User.class,
    new QueryWrapper<User>().eq("active", true));

// List by IDs
List<User> specificUsers = Db.listByIds(User.class, Arrays.asList(1L, 2L, 3L));

// List by column map
Map<String, Object> conditions = new HashMap<>();
conditions.put("active", true);
conditions.put("age", 30);
List<User> users = Db.listByMap(User.class, conditions);

Count and Existence

// Count all
long totalUsers = Db.count(User.class);
System.out.println("Total users: " + totalUsers);

// Count with conditions
long activeUsers = Db.count(User.class, 
    new QueryWrapper<User>().eq("active", true));

long adultUsers = Db.count(User.class,
    new QueryWrapper<User>().ge("age", 18));

// Check existence
boolean hasActiveUsers = Db.exists(User.class,
    new QueryWrapper<User>().eq("active", true));

if (hasActiveUsers) {
    System.out.println("Active users exist");
}

Update Operations

// Update by ID
User user = Db.getById(User.class, 1L);
if (user != null) {
    user.setEmail("updated@example.com");
    user.setUpdatedTime(LocalDateTime.now());
    boolean updated = Db.updateById(user);
}

// Update with conditions (using wrapper only)
boolean updated = Db.update(User.class,
    new UpdateWrapper<User>()
        .set("active", false)
        .set("updated_time", LocalDateTime.now())
        .eq("last_login", null)
);

// Update with entity and conditions
User updateEntity = new User();
updateEntity.setActive(false);
boolean updated = Db.update(User.class, updateEntity,
    new UpdateWrapper<User>().gt("age", 65));

// Batch update by IDs
List<User> usersToUpdate = Db.listByIds(User.class, Arrays.asList(1L, 2L, 3L));
usersToUpdate.forEach(user -> user.setActive(true));
boolean allUpdated = Db.updateBatchById(usersToUpdate);

Remove Operations

// Remove by entity (uses entity's ID)
User user = Db.getById(User.class, 1L);
boolean removed = Db.removeById(user);

// Remove by class and ID
boolean removed = Db.removeById(User.class, 1L);

// Remove by IDs
boolean removed = Db.removeByIds(User.class, Arrays.asList(1L, 2L, 3L));

// Remove by column map
Map<String, Object> conditions = new HashMap<>();
conditions.put("active", false);
conditions.put("last_login", null);
boolean removed = Db.removeByMap(User.class, conditions);

// Remove with conditions
boolean removed = Db.remove(User.class,
    new QueryWrapper<User>()
        .eq("active", false)
        .lt("created_time", LocalDateTime.now().minusYears(1))
);

Pagination with Static Methods

// Basic pagination
Page<User> page = new Page<>(1, 10);
Page<User> result = Db.page(User.class, page);

List<User> users = result.getRecords();
long total = result.getTotal();

// Pagination with conditions
Page<User> conditionPage = Db.page(User.class, new Page<>(1, 15),
    new QueryWrapper<User>().eq("active", true).orderByDesc("created_time"));

// Paginate map results
Page<Map<String, Object>> mapPage = Db.pageMaps(User.class, new Page<>(1, 10),
    new QueryWrapper<User>().select("id", "name", "email"));

Object Mapping and Maps

// Get as map
Map<String, Object> userMap = Db.getMap(User.class,
    new QueryWrapper<User>().eq("id", 1L));

// List as maps
List<Map<String, Object>> userMaps = Db.listMaps(User.class,
    new QueryWrapper<User>().eq("active", true));

// List specific objects
List<String> emails = Db.listObjs(User.class,
    new QueryWrapper<User>().select("email").eq("active", true),
    Object::toString);

// List all emails
List<String> allEmails = Db.listObjs(User.class, Object::toString);

Chain Operations with Static Methods

// Query chains
List<User> activeUsers = Db.query(User.class)
    .eq("active", true)
    .gt("age", 18)
    .orderByDesc("created_time")
    .list();

User user = Db.lambdaQuery(User.class)
    .eq(User::getActive, true)
    .eq(User::getEmail, "john@example.com")
    .one();

// Update chains
boolean updated = Db.update(User.class)
    .set("last_login", LocalDateTime.now())
    .eq("id", 1L)
    .update();

boolean deactivated = Db.lambdaUpdate(User.class)
    .set(User::getActive, false)
    .isNull(User::getLastLogin)
    .update();

// Remove with chains
boolean removed = Db.update(User.class)
    .eq("active", false)
    .lt("created_time", LocalDateTime.now().minusMonths(6))
    .remove();

ChainWrappers Factory Usage

// Using ChainWrappers with entity class
List<User> users = ChainWrappers.queryChain(User.class)
    .eq("department", "IT")
    .isNotNull("email")
    .orderByAsc("name")
    .list();

boolean updated = ChainWrappers.updateChain(User.class)
    .set("department", "Engineering")
    .eq("department", "IT")
    .update();

// Lambda chains with ChainWrappers
List<User> managers = ChainWrappers.lambdaQueryChain(User.class)
    .eq(User::getRole, "MANAGER")
    .isNotNull(User::getTeamId)
    .orderByDesc(User::getCreatedTime)
    .list();

boolean updated = ChainWrappers.lambdaUpdateChain(User.class)
    .set(User::getStatus, "ACTIVE")
    .eq(User::getRole, "USER")
    .update();

Advanced Usage Patterns

Utility Class Implementation

public class UserUtils {
    
    // Static utility methods using Db class
    public static List<User> findActiveUsersByDepartment(String department) {
        return Db.list(User.class,
            new QueryWrapper<User>()
                .eq("active", true)
                .eq("department", department)
                .orderByAsc("name")
        );
    }
    
    public static boolean deactivateInactiveUsers(int inactiveDays) {
        LocalDateTime cutoffDate = LocalDateTime.now().minusDays(inactiveDays);
        return Db.update(User.class,
            new UpdateWrapper<User>()
                .set("active", false)
                .set("deactivated_time", LocalDateTime.now())
                .lt("last_login", cutoffDate)
                .eq("active", true)
        );
    }
    
    public static long countUsersByRole(String role) {
        return Db.count(User.class,
            new QueryWrapper<User>().eq("role", role).eq("active", true)
        );
    }
    
    public static Page<User> searchUsers(String keyword, int page, int size) {
        return Db.page(User.class, new Page<>(page, size),
            new QueryWrapper<User>()
                .and(wrapper -> wrapper
                    .like("name", keyword)
                    .or()
                    .like("email", keyword)
                )
                .eq("active", true)
                .orderByDesc("created_time")
        );
    }
    
    public static boolean bulkUpdateUserStatus(List<Long> userIds, String status) {
        return Db.update(User.class,
            new UpdateWrapper<User>()
                .set("status", status)
                .set("updated_time", LocalDateTime.now())
                .in("id", userIds)
        );
    }
    
    public static void cleanupOldInactiveUsers() {
        LocalDateTime cutoffDate = LocalDateTime.now().minusYears(2);
        Db.remove(User.class,
            new QueryWrapper<User>()
                .eq("active", false)
                .lt("deactivated_time", cutoffDate)
        );
    }
}

Scheduled Tasks

@Component
public class UserMaintenanceScheduler {
    
    @Scheduled(cron = "0 0 2 * * ?") // Daily at 2 AM
    public void deactivateInactiveUsers() {
        // Deactivate users inactive for 90 days
        LocalDateTime cutoffDate = LocalDateTime.now().minusDays(90);
        
        long count = Db.update(User.class,
            new UpdateWrapper<User>()
                .set("active", false)
                .set("deactivated_time", LocalDateTime.now())
                .lt("last_login", cutoffDate)
                .eq("active", true)
        ) ? 1 : 0;
        
        if (count > 0) {
            System.out.println("Deactivated inactive users");
        }
    }
    
    @Scheduled(cron = "0 0 3 * * 0") // Weekly on Sunday at 3 AM
    public void cleanupOldData() {
        // Remove users inactive for over 2 years
        LocalDateTime cutoffDate = LocalDateTime.now().minusYears(2);
        
        boolean removed = Db.remove(User.class,
            new QueryWrapper<User>()
                .eq("active", false)
                .lt("deactivated_time", cutoffDate)
        );
        
        if (removed) {
            System.out.println("Cleaned up old inactive user data");
        }
    }
}

Data Migration Utilities

public class DataMigrationUtils {
    
    public static void migrateUserRoles() {
        // Update old role format to new format
        Db.update(User.class,
            new UpdateWrapper<User>()
                .set("role", "ADMIN")
                .eq("role", "admin")
        );
        
        Db.update(User.class,
            new UpdateWrapper<User>()
                .setSql("role = UPPER(role)")
                .ne("role", "ADMIN")
        );
    }
    
    public static void addDefaultValues() {
        // Add default values for users missing certain fields
        Db.update(User.class,
            new UpdateWrapper<User>()
                .set("status", "ACTIVE")
                .isNull("status")
        );
        
        Db.update(User.class,
            new UpdateWrapper<User>()
                .set("created_time", LocalDateTime.now())
                .isNull("created_time")
        );
    }
    
    public static void normalizeEmailAddresses() {
        // Normalize email addresses to lowercase
        List<User> users = Db.list(User.class,
            new QueryWrapper<User>().isNotNull("email")
        );
        
        List<User> toUpdate = users.stream()
            .filter(user -> !user.getEmail().equals(user.getEmail().toLowerCase()))
            .peek(user -> user.setEmail(user.getEmail().toLowerCase()))
            .collect(Collectors.toList());
        
        if (!toUpdate.isEmpty()) {
            Db.updateBatchById(toUpdate);
        }
    }
}

Configuration and Cache Integration

@Component
public class UserCacheManager {
    
    @Cacheable(value = "users", key = "#id")
    public User getCachedUser(Long id) {
        return Db.getById(User.class, id);
    }
    
    @CacheEvict(value = "users", key = "#user.id")
    public boolean updateUserWithCacheEviction(User user) {
        return Db.updateById(user);
    }
    
    @CacheEvict(value = "users", allEntries = true)
    public void clearUserCache() {
        // Cache will be cleared after method execution
    }
    
    public List<User> getActiveUsersWithCache() {
        // Check cache first, then database
        return Db.list(User.class,
            new QueryWrapper<User>().eq("active", true)
        );
    }
}

Best Practices

1. Error Handling

public class SafeDbOperations {
    
    public static Optional<User> safeGetById(Long id) {
        try {
            return Db.getOptById(User.class, id);
        } catch (Exception e) {
            System.err.println("Error fetching user by ID " + id + ": " + e.getMessage());
            return Optional.empty();
        }
    }
    
    public static boolean safeSave(User user) {
        try {
            return Db.save(user);
        } catch (Exception e) {
            System.err.println("Error saving user: " + e.getMessage());
            return false;
        }
    }
}

2. Parameter Validation

public class ValidatedDbOperations {
    
    public static List<User> findUsersByIds(Collection<Long> ids) {
        if (ids == null || ids.isEmpty()) {
            return Collections.emptyList();
        }
        
        return Db.listByIds(User.class, ids);
    }
    
    public static long countActiveUsers() {
        return Db.count(User.class,
            new QueryWrapper<User>().eq("active", true)
        );
    }
}

3. Performance Considerations

public class PerformantDbOperations {
    
    // Use batch operations for multiple records
    public static boolean saveUsers(List<User> users) {
        if (users.size() > 100) {
            return Db.saveBatch(users, 50); // Custom batch size
        } else {
            return Db.saveBatch(users);
        }
    }
    
    // Use specific field selection when possible
    public static List<String> getUserEmails() {
        return Db.listObjs(User.class,
            new QueryWrapper<User>()
                .select("email")
                .eq("active", true),
            Object::toString
        );
    }
    
    // Use pagination for large result sets
    public static Page<User> getLargeUserSet(int page, int size) {
        return Db.page(User.class,
            new Page<User>(page, size).setOptimizeCountSql(true)
        );
    }
}

The static utility approach is particularly useful for:

  • Utility classes and helper methods
  • Scheduled tasks and background jobs
  • Data migration scripts
  • Static initialization blocks
  • Testing scenarios where dependency injection is not available
  • Simple CRUD operations without complex business logic

Install with Tessl CLI

npx tessl i tessl/maven-com-baomidou--mybatis-plus-extension

docs

active-record.md

condition-builders.md

index.md

kotlin-extensions.md

pagination.md

plugin-system.md

service-layer.md

static-utilities.md

tile.json