作者:京东科技 张新磊
文章背景
最近在测试业务需求时通读了研发指定需求的代码,发现研发大佬们用到了如下的内容,有些内容我还不是十分的清楚,比如下述真实代码;作为后端大佬肯定炉火纯青,但是我刚刚看到这段代码时确实有点懵;
快速理解的方式
直接借助 joycoder 解释代码的能力就可以快速理解
于是乎有了下述的探索
但是我为了理解的透彻点还是又去翻找了一些其它资料做一个记录吧,后续万一在遗忘了也方便快速查找
MyBatis-Plus 的 LambdaQueryWrapper 简介
LambdaQueryWrapper 是 MyBatis-Plus 提供的一种类型安全的查询条件构造器,它利用 Java 8 的 Lambda 表达式特性,避免了硬编码字段名,提高了代码的可读性和可维护性。
基本用法示例
 LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>();queryWrapper.eq(User::getName, "张三")           .ge(User::getAge, 18)           .orderByDesc(User::getCreateTime);List userList = userMapper.selectList(queryWrapper);
   复制代码
 LambdaQueryWrapper 的优势
类型安全:通过方法引用而非字符串指定字段,编译器可检查类型
代码可读性高:链式调用,语义清晰
防止 SQL 注入:自动处理参数绑定
智能提示:IDE 可自动补全字段名
Spring Boot 的 @Async 异步处理
@Async 是 Spring 框架提供的注解,用于标记方法为异步执行。被 @Async 注解的方法会在调用时立即返回,而实际执行将发生在单独的线程中。
基本配置
首先需要在 Spring Boot 启动类或配置类上添加 @EnableAsync 注解:
 @SpringBootApplication@EnableAsyncpublic class MyApplication {    public static void main(String[] args) {        SpringApplication.run(MyApplication.class, args);    }}
   复制代码
 简单使用示例
 @Servicepublic class AsyncService {
    @Async    public void asyncMethod() {        // 这个方法将在单独的线程中执行        System.out.println("执行异步方法: " + Thread.currentThread().getName());    }}
   复制代码
 LambdaQueryWrapper 与 @Async 的结合实践
将两者结合使用可以实现高效的异步数据库操作,特别适合那些不需要立即返回结果的复杂查询或批量操作。
示例 1:异步查询用户列表
 @Service@RequiredArgsConstructorpublic class UserService {        private final UserMapper userMapper;        @Async    public CompletableFuture> asyncFindUsers(String name, Integer minAge) {        LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>();        queryWrapper.like(StringUtils.isNotBlank(name), User::getName, name)                   .ge(minAge != null, User::getAge, minAge);                List users = userMapper.selectList(queryWrapper);        return CompletableFuture.completedFuture(users);    }}
   复制代码
 示例 2:异步统计与保存
 @Asyncpublic void asyncStatAndSave(Long departmentId) {    // 统计部门人数    LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>();    queryWrapper.eq(User::getDepartmentId, departmentId);    long count = userMapper.selectCount(queryWrapper);        // 更新统计结果    Department department = new Department();    department.setId(departmentId);    department.setUserCount(count);    departmentMapper.updateById(department);        // 记录统计日志    StatLog statLog = new StatLog();    statLog.setDepartmentId(departmentId);    statLog.setCount(count);    statLog.setStatTime(LocalDateTime.now());    statLogMapper.insert(statLog);}
   复制代码
 高级应用与优化
自定义线程池配置
默认情况下,@Async 使用 SimpleAsyncTaskExecutor,这不是生产环境的最佳选择。我们可以自定义线程池:
 @Configurationpublic class AsyncConfig implements AsyncConfigurer {        @Override    public Executor getAsyncExecutor() {        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();        executor.setCorePoolSize(10);        executor.setMaxPoolSize(50);        executor.setQueueCapacity(100);        executor.setThreadNamePrefix("AsyncExecutor-");        executor.initialize();        return executor;    }}
   复制代码
 异常处理
异步方法的异常不会传播到调用线程,需要特别处理:
 @Asyncpublic CompletableFuture> asyncFindUsersWithExceptionHandling(String name) {    try {        LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>();        queryWrapper.like(User::getName, name);        List users = userMapper.selectList(queryWrapper);        return CompletableFuture.completedFuture(users);    } catch (Exception e) {        // 记录日志        log.error("异步查询用户失败", e);        // 返回空列表或抛出CompletionException        return CompletableFuture.completedFuture(Collections.emptyList());    }}
   复制代码
 事务处理
@Async 方法的事务需要特别注意,默认情况下异步方法的事务不会传播:
 @Async@Transactional(propagation = Propagation.REQUIRES_NEW)public void asyncUpdateWithTransaction(User user) {    // 这个更新操作将在新事务中执行    userMapper.updateById(user);}
   复制代码
 
实际应用场景
后台报表生成
 @Asyncpublic void asyncGenerateUserReport(LocalDate startDate, LocalDate endDate, String reportPath) {    LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>();    queryWrapper.between(User::getCreateTime, startDate.atStartOfDay(), endDate.atTime(23, 59, 59))               .orderByAsc(User::getCreateTime);        List users = userMapper.selectList(queryWrapper);        // 生成报表文件    generateExcelReport(users, reportPath);        // 发送通知    sendReportReadyNotification(reportPath);}
   复制代码
 批量数据处理
 @Asyncpublic CompletableFuture asyncBatchProcessUsers(List userIds) {    LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>();    queryWrapper.in(User::getId, userIds);        List users = userMapper.selectList(queryWrapper);        int processedCount = 0;    for (User user : users) {        if (processUser(user)) {            processedCount++;        }    }    return CompletableFuture.completedFuture(processedCount);}
   复制代码
 
性能考量与最佳实践
合理使用异步:不是所有数据库操作都适合异步,简单查询同步执行可能更高效
控制并发量:避免过多并发数据库连接导致系统资源耗尽
批量操作优化:考虑使用 MyBatis-Plus 的批量操作方法
结果处理:使用 CompletableFuture 可以方便地处理异步结果
监控:监控异步任务的执行情况和线程池状态
总结
MyBatis-Plus 的 LambdaQueryWrapper 与 Spring Boot 的 @Async 注解的结合,为 Java 后端开发提供了强大的工具组合。LambdaQueryWrapper 提供了类型安全、优雅的查询构建方式,而 @Async 则让异步编程变得简单。合理使用这两者可以显著提高应用程序的响应速度和处理能力,特别是在处理复杂查询、批量操作和后台任务时。
在实际项目中,开发者应根据具体场景选择合适的技术组合,并注意线程池配置、异常处理和事务管理等关键点,以确保系统的稳定性和可靠性。
评论