Spring boot 当两个作业尝试使用同一个表时,Spring批处理锁定资源

Spring boot 当两个作业尝试使用同一个表时,Spring批处理锁定资源,spring-boot,spring-batch,Spring Boot,Spring Batch,我使用的是Spring boot&Spring batch,如果表A(表A)中已经有作业,我想锁定表A中的访问权限,因此我想将作业放在等待列表中,直到上一个作业完成并重新启动已停止的作业 目前,我可以使用**JobExecutionListener**的**beforeJob**和**afterJob**方法停止同一实例的作业,并在另一个作业(具有同一实例)结束时重新启动它。但当两个不同的作业具有相同的参数(访问相同的表)时,我无法进行检查 这是我的密码: private void runJob

我使用的是Spring boot&Spring batch,如果表A(表A)中已经有作业,我想锁定表A中的访问权限,因此我想将作业放在等待列表中,直到上一个作业完成并重新启动已停止的作业

目前,我可以使用**JobExecutionListener**的**beforeJob**和**afterJob**方法停止同一实例的作业,并在另一个作业(具有同一实例)结束时重新启动它。但当两个不同的作业具有相同的参数(访问相同的表)时,我无法进行检查

这是我的密码:

private void runJobB(Job parJob) throws Exception {

        log.info("[Job] running ...........");

        Map<String, JobParameter> confMap = new HashMap<>();

        confMap.put("value", new JobParameter("label_test"));
        confMap.put("time", new JobParameter(System.currentTimeMillis()));
        JobParameters jobParameters = new JobParameters(confMap);

        try {
            jobLauncher.run(parJob, jobParameters);
        } catch (Exception ex) {
            log.error("job1 : " + ex.getMessage());
        }
    }
private void runJobB(作业parJob)引发异常{
log.info(“[作业]正在运行…………”);
Map confMap=newhashmap();
confMap.put(“值”,新作业参数(“标签测试”);
confMap.put(“time”,新作业参数(System.currentTimeMillis());
JobParameters JobParameters=新的JobParameters(confMap);
试一试{
jobLauncher.run(parJob,jobParameters);
}捕获(例外情况除外){
log.error(“job1:+ex.getMessage());
}
}
公共类拦截JobExecution实现JobExecutionListener{
静态私有映射jobInformationsMap=newHashMap();
@自动连线
私人JobExplorer;
@自动连线
私有作业库作业库;
@自动连线
私人职业经营者;
@鬼鬼祟祟
@凌驾
作业前公共无效(作业执行作业执行){
log.info(“拦截作业执行-作业前!”);
最后一个字符串locJobName=jobExecution.getJobInstance().getJobName();
最终列表jobExecutionList=新的ArrayList(jobExplorer.findRunningJobExecutions(locJobName));
if(jobExecutionList.size()>1){
for(JobExecution jobExecution1:jobExecutionList){
已同步(作业执行1){
jobInformationsMap.put(jobExecution1.getId(),jobExecution1);
jobExecution1.setEndTime(新日期());
jobExecution1.setStatus(BatchStatus.FAILED);
jobExecution1.setExitStatus(ExitStatus.FAILED);
jobExecution1.stop();
}
}
}
}
私有void restart(){
试一试{
final Map.Entry first=getFirst();
final JobExecution JobExecution=first.getValue();
已同步(作业执行){
if(jobExecution.getStatus().equals(BatchStatus.STOPPING)){
jobRepository.update(作业执行);
重新启动(jobExecution.getId());
}
}
}捕获(异常e1){
e1.printStackTrace();
}
}
@鬼鬼祟祟
@凌驾
公共无效后作业(作业执行作业执行){
已同步(作业执行){
log.info(“拦截作业执行-作业后!”);
如果(作业信息映射大小()>1){
重启();
}
}
}
私有静态映射。条目getFirst(){
Map.Entry locJobExecution=null;
Date minCreateTime=Calendar.getInstance().getTime();
对于(Map.Entry locMap:jobInformationsMap.entrySet()){
最终日期createTime=locMap.getValue().getCreateTime();
if(minCreateTime.after(createTime)){
minCreateTime=createTime;
locJobExecution=locMap;
}
}
jobInformationsMap.remove(locJobExecution.getKey());
返回执行;
}
}

我到处都搜索过,但如果您能帮助我,我找不到与我想要的完全匹配的内容,谢谢。

您遇到的是作业编排设计问题,而不是实施问题。你为什么不一个接一个地开始工作呢
我想将作业放在等待列表中,直到上一个作业完成为止
:使用作业请求队列并按顺序启动它们。
public class InterceptingJobExecution implements JobExecutionListener {
    static private Map<Long, JobExecution> jobInformationsMap = new HashMap<>();

    @Autowired
    private JobExplorer jobExplorer;
    @Autowired
    private JobRepository jobRepository;
    @Autowired
    private JobOperator jobOperator;

    @SneakyThrows
    @Override
    public void beforeJob(JobExecution jobExecution) {
        log.info("Intercepting Job Excution - Before Job!");

        final String locJobName = jobExecution.getJobInstance().getJobName();

        final List<JobExecution> jobExecutionList = new ArrayList<>(jobExplorer.findRunningJobExecutions(locJobName));

        if (jobExecutionList.size() > 1) {
            for (JobExecution jobExecution1 : jobExecutionList) {
                synchronized (jobExecution1) {
                    jobInformationsMap.put(jobExecution1.getId(), jobExecution1);
                    jobExecution1.setEndTime(new Date());
                    jobExecution1.setStatus(BatchStatus.FAILED);
                    jobExecution1.setExitStatus(ExitStatus.FAILED);
                    jobExecution1.stop();
                }
            }
        }
    }

    private void restart() {
        try {
            final Map.Entry<Long, JobExecution> first = getFirst();
            final JobExecution jobExecution = first.getValue();

            synchronized (jobExecution) {
                if(jobExecution.getStatus().equals(BatchStatus.STOPPING)) {
                    jobRepository.update(jobExecution);
                    jobOperator.restart(jobExecution.getId());
                }
            }

        } catch (Exception e1) {
            e1.printStackTrace();
        }
    }

    @SneakyThrows
    @Override
    public void afterJob(JobExecution jobExecution) {
        synchronized (jobExecution) {
            log.info("Intercepting Job Excution - After Job!");

            if(jobInformationsMap.size() > 1) {
                restart();
            }

        }
    }

    private static Map.Entry<Long, JobExecution> getFirst() {
        Map.Entry<Long, JobExecution> locJobExecution = null;
        Date minCreateTime = Calendar.getInstance().getTime();

        for( Map.Entry<Long, JobExecution> locMap : jobInformationsMap.entrySet()) {
            final Date createTime = locMap.getValue().getCreateTime();
            if(minCreateTime.after(createTime)) {
                minCreateTime = createTime;
                locJobExecution = locMap;
            }
        }
        jobInformationsMap.remove(locJobExecution.getKey());

        return locJobExecution;
    }

}