我有以下情况:
如何实现这一目标?我不想在步骤5中使用锁定表。步骤1-4的行为应该类似于“SELECT FOR UPDATE”。以下是我目前的代码。我正在执行的方法是 execute()。我正在测试它是通过从不同的应用程序实例执行它而我正在检查,如果实例A能够在表上执行操作而实例B正在执行 executeJob(job)。
@Service
@Slf4j
@Transactional
public class JobExecutionService {
private final Environment environment;
private final TestJobRepository testJobRepository;
private final TestJobResultRepository testJobResultRepository;
@Autowired
public JobExecutionService(Environment environment, TestJobRepository testJobRepository, TestJobResultRepository testJobResultRepository) {
this.environment = environment;
this.testJobRepository = testJobRepository;
this.testJobResultRepository = testJobResultRepository;
}
public void execute() {
TestJob job = getJob();
executeJob(job);
finishJob(job);
}
@Transactional
public TestJob getJob() {
TestJob testJob = testJobRepository.findFirstByStatusOrderByIdAsc(
0
);
testJob.setStatus(1);
testJobRepository.save(testJob);
return testJob;
}
public void executeJob(TestJob testJob) {
log.debug("Execution-0: {}", testJob.toString());
Random random = new Random();
try {
Thread.sleep(random.nextInt(3000) + 1000);
} catch (InterruptedException e) {
log.error("Error", e);
}
log.debug("Execution-1: {}", testJob.toString());
}
@Transactional(propagation = Propagation.REQUIRES_NEW)
public void finishJob(TestJob testJob) {
testJobResultRepository.save(
new TestJobResult(
null,
testJob.getId(),
environment.getProperty("local.server.port")
)
);
}
}
public interface TestJobRepository extends PagingAndSortingRepository<TestJob, Long>, QueryDslPredicateExecutor<TestJob> {
@Lock(LockModeType.PESSIMISTIC_WRITE)
TestJob findFirstByStatusOrderByIdAsc(Integer status);
}
答案 0 :(得分:4)
@Transactional
在代理模式下不起作用:Does Spring @Transactional attribute work on a private method?这里唯一的一个公共方法是execute()
,所以你可以注释它或整个类
(顺便说一下,如果您公开getJob()
和finishJob()
,@Transactional
仍然无效,因为execute()
方法通过{{1}调用它们而不是通过事务管理基础结构生成的代理。)
您可以从this
中删除@Transactional
,移动JobExecutionService
和getJob()
(或在独立交易中应运行的任何方法)作为新服务的公共方法,例如{ {1}}并将新服务注释为finishJob()
。