Grails 3 数据库保存后执行作业:仅User表有激活用户时触发Quartz作业
Quartz作业条件触发实现方案
核心思路
将触发逻辑拆解为三个关联节点:绑定数据库保存完成的后置回调 → 回调中校验User表active用户存在性 → 校验通过后触发Quartz作业,保证逻辑顺序和判断准确性。
具体实现步骤
- 第一步:绑定事务完成回调
优先绑定事务提交后的回调钩子,避免事务未提交导致读取不到最新数据的问题。
Spring框架场景直接使用@TransactionalEventListener注解,指定执行阶段为TransactionPhase.AFTER_COMMIT;非Spring场景直接在业务代码的事务提交语句之后插入回调逻辑即可。
参考示例代码:// 1. 自定义保存完成事件 public class DataSavedEvent extends ApplicationEvent { public DataSavedEvent(Object source) { super(source); } } // 2. 保存操作完成后发布事件 @Service public class BizDataService { private final ApplicationEventPublisher eventPublisher; @Transactional public void saveBizData(BizData data) { // 原有保存业务逻辑 bizMapper.insert(data); // 发布保存完成事件 eventPublisher.publishEvent(new DataSavedEvent(data)); } } - 第二步:新增active用户校验逻辑
编写高效存在性查询SQL,不要全表扫描,只要判断是否至少有一条符合条件的记录即可:
校验时注意读主库,避免主从同步延迟导致判断错误,同时不要走二级缓存,确保拿到最新的用户状态。SELECT 1 FROM user WHERE status = 'active' LIMIT 1 - 第三步:校验通过后触发Quartz作业
如果查询到存在active用户,调用Quartz调度器接口触发作业即可,需要立即执行一次的场景参考如下代码:@Component public class DataSavedEventListener { private final UserMapper userMapper; private final Scheduler quartzScheduler; @TransactionalEventListener(phase = TransactionPhase.AFTER_COMMIT) public void handleAfterSave(DataSavedEvent event) throws SchedulerException { Boolean hasActiveUser = userMapper.checkHasActiveUser(); if (Boolean.TRUE.equals(hasActiveUser)) { // 替换为你自己的作业名和作业组 quartzScheduler.triggerJob(JobKey.jobKey("customJob", "bizGroup")); } } }
优化建议
- 如果作业触发频率很高,可以给active用户的存在状态做个30s以内的短缓存,减少数据库查询压力
- 可以给作业增加幂等校验,避免重复触发导致的业务异常
- 如果是修改用户状态的保存操作,建议直接在修改逻辑中同步更新缓存的存在状态,不需要每次都查库
内容的提问来源于stack exchange,提问作者Gunsmokaz
相关产品推荐
相关产品推荐

