0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

LambdaQueryWrapper遇上@Async

京东云 ? 来源:jf_75140285 ? 作者:jf_75140285 ? 2025-07-14 14:55 ? 次阅读
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

文章背景

最近在测试业务需求时通读了研发指定需求的代码,发现研发大佬们用到了如下的内容,有些内容我还不是十分的清楚,比如下述真实代码;作为后端大佬肯定炉火纯青,但是我刚刚看到这段代码时确实有点懵;

快速理解的方式
直接借助joycoder解释代码的能力就可以快速理解

wKgZO2h0qe2AS6_FAANiXU5FIDM053.png


于是乎有了下述的探索

wKgZPGh0qe6AK-ccAAOZgbwBR5E034.png


但是我为了理解的透彻点还是又去翻找了一些其它资料做一个记录吧,后续万一在遗忘了也方便快速查找

wKgZO2h0qe-AI0uuAAOZgbwBR5E369.png

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
@EnableAsync
public class MyApplication {
    public static void main(String[] args) {
        SpringApplication.run(MyApplication.class, args);
    }
}

简单使用示例

@Service
public class AsyncService {

    @Async
    public void asyncMethod() {
        // 这个方法将在单独的线程中执行
        System.out.println("执行异步方法: " + Thread.currentThread().getName());
    }
}

LambdaQueryWrapper与@Async的结合实践

将两者结合使用可以实现高效的异步数据库操作,特别适合那些不需要立即返回结果的复杂查询或批量操作。

示例1:异步查询用户列表

@Service
@RequiredArgsConstructor
public 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:异步统计与保存

@Async
public 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,这不是生产环境的最佳选择。我们可以自定义线程池:

@Configuration
public 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;
    }
}

异常处理

异步方法的异常不会传播到调用线程,需要特别处理:

@Async
public 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);
}

实际应用场景

后台报表生成

@Async
public 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);
}

批量数据处理

@Async
public 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则让异步编程变得简单。合理使用这两者可以显著提高应用程序的响应速度和处理能力,特别是在处理复杂查询、批量操作和后台任务时。
在实际项目中,开发者应根据具体场景选择合适的技术组合,并注意线程池配置、异常处理和事务管理等关键点,以确保系统的稳定性和可靠性。

审核编辑 黄宇

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • JAVA
    +关注

    关注

    20

    文章

    2989

    浏览量

    110749
  • 代码
    +关注

    关注

    30

    文章

    4905

    浏览量

    70956
收藏 人收藏
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

    评论

    相关推荐
    热点推荐

    电磁遇上热与应力-CST多物理场仿真解决复杂工程挑战

    当电磁遇上热与应力,CST MPhysics Studio提供真正的全耦合多物理场仿真能力。电磁-热耦合、热失谐分析、热-机械耦合、电磁-机械耦合,解决复杂工程挑战。
    的头像 发表于 07-29 16:21 ?122次阅读
    电磁<b class='flag-5'>遇上</b>热与应力-CST多物理场仿真解决复杂工程挑战

    当Modbus遇上Profinet:阀门通信的“破圈”神助攻

    现场跑得多的工程师都知道,自动化车间里总有那么些“新旧混搭”的头疼事——老款阀门还在用Modbus协议兢兢业业干活,新上的控制系统却清一色认准了Profinet。一边是靠谱的“老伙计”,一边是高效的“新平台”,怎么让它们搭上线?这时候,耐达讯自动化Modbus转Profinet网关的“翻译官”就得登场了。 举个真实案例:某化工厂的反应釜阀门组,5台老闸阀用Modbus RTU通信,新上的西门子PLC却只认Profinet。刚开始硬接试过不少招,要么数据丢包让阀门开关延迟,要么误报“通信故障”导致停机,折腾了三天没搞定。后来换上耐达讯自动化转换网关,把Modbus的寄存器地址精准映射到Profinet的IO数据区,阀门状态、控制指令秒级同步,至今稳定运行半年多,操作工都说“终于不用盯着报警灯发呆了”。 技术上得拎清两个关键点:一是“翻译”要精准,Modbus的16位寄存器和Profinet的32位浮点数得对应无误,比如阀门开度0-100%的数值转换不能差毫厘;二是“抗造”得过关,车间里电机、变频器的电磁干扰可不是闹着玩的,网关得带光电隔离和浪涌保护,不然信号分分钟被“杂音”淹没。 说白了,这小小的转换网关,玩的就是“无缝衔接”的活儿。它不用改老阀门的程序,也不用动新系统的配置,插上电、设好参数,Modbus的“方言”立马能转成Profinet的“普通话”。老阀门不用下岗,新系统的优势全发挥,整个控制链路响应速度提上来,停机调试时间砍下去,这不就是咱们工程师最想看到的“降本增效”吗? 总之,在自动化升级的赛道上,别让协议差异拖了后腿。耐达讯自动化Modbus转Profinet网关这步“神操作”,既能保住老设备的价值,又能让新系统跑起来更顺,堪称阀门通信的“性价比之王”。毕竟,让设备们好好“对话”,生产线才能跑得更欢实,不是吗?
    发表于 07-25 15:37

    使用BLE(CYW20829)作为SPI slave和MCU(TC387)作为SPI master,调试SPI通信时遇到的问题求解

    尝试:调试过程中发现,slave 使用 cyhal_spi_slave_write时,rx中断正常触发,看代码该函数调用了 cyhal_spi_transfer_async。 问题:只有slave
    发表于 07-01 08:28

    当ASM焊线机遇上协议翻译官:CC\\-Link IE转Modbus RTU的节能数据之旅

    车间环境,让数据流稳定无虞。 实战瞬间:电流监测难题迎刃而解 某电子厂在部署能源管理系统时遭遇上述困境。工程师在ASM焊线机与Modbus RTU能耗平台间部署协议网关: 配置: 通过网页快速设定
    发表于 06-26 14:38

    当机器人遇上“语言障碍”:CCLINKIE转Profinet的“破冰外挂”来啦\\!

    在汽车焊装车间的技术角,工程师小陈的笔记本记满了“跨协议难题”:当搭载Profinet的库卡机器人遇上CCLINKIE总线的三菱PLC,数据交互像隔着玻璃喊话——PLC发送的坐标指令要“绕地球半圈
    发表于 06-04 14:31

    CANoe产品体系19版本新功能(下)

    NET 8.0现已支持测试脚本、应用模型和仿真节点的开发,支持C# 12,可使用async/await进行等待,本机编译实现快速加载,改进应用层对象的API实现处理复杂数据类型,并支持运行在Linux版本CANoe SE中。
    的头像 发表于 05-29 14:05 ?977次阅读
    CANoe产品体系19版本新功能(下)

    跨异步时钟域处理方法大全

    该方法只用于慢到快时钟域的1bit信号传递。在Xilinx器件中,可以使用(* ASYNC_REG = "TRUE" *)标记,将两个寄存器尽量靠近综合,降低 亚稳态因导线延迟太大而传播到第二个寄存器的可能性。
    的头像 发表于 05-14 15:33 ?713次阅读
    跨异步时钟域处理方法大全

    当冲压焊接遇上Canopen到Profinet协议转换网关

    Profinet
    小疆智控
    发布于 :2025年05月13日 15:09:54

    HID免驱升级例程,基于nodejs编写

    async function usbhid_main()?{? ?// 打印所有参数? ?let path = args[0];? ?console.log('\n欢迎使用USB HID
    发表于 04-28 17:58 ?0次下载

    进程、线程、协程傻傻分不清?一文带你彻底扒光它们的\"底裤\"!

    :\"我去关火!\"( yield 控制权) 代码示例(Python异步爬虫): python import asyncio import aiohttp ? async def fetch
    发表于 03-26 09:27

    获取具有三个输出的自定义模型的输出张量,运行时错误是怎么回事?

    () infer_request.start_async() infer_request.wait() output = infer_request.get_output_tensor() 打印(输出) 收到的错误: 运行时错误:必须对只有一个参数的函数调用 get_output_tensor()。
    发表于 03-05 09:44

    普渡机器人PUDU SH1如何助力酒店服务升级

    当传统清洁遇上人力短缺、效率瓶颈,酒店如何破局?
    的头像 发表于 02-26 09:22 ?533次阅读

    精密仪器检测遇上索尼FCB-EV9520L:解锁高效与精准的新篇章

    在高度精密与自动化的工业检测领域,视频设备作为“视觉之眼”,其性能直接关乎到生产线的效率与产品质量。当精密仪器检测遇上索尼FCB-EV9520L模组一体化机芯控制板时,一场关于高效与精准的技术革新
    的头像 发表于 12-05 11:09 ?462次阅读

    IB Verbs和NVIDIA DOCA GPUNetIO性能测试

    Async 等技术,能够创建以 GPU 为中心的应用程序,其中 CUDA 内核可以直接与网卡(NIC)通信,从而绕过 CPU 发送和接收数据包,并将 CPU 排除在关键路径之外。
    的头像 发表于 08-23 17:03 ?1436次阅读
    IB Verbs和NVIDIA DOCA GPUNetIO性能测试

    一本小册子,咋就让IT人水灵灵地「由I变E」了?

    当IT圈遇上MBTI,看「I人」如何秒变「E人」!
    的头像 发表于 08-12 14:28 ?1622次阅读
    一本小册子,咋就让IT人水灵灵地「由I变E」了?