【发布时间】:2017-05-03 17:45:45
【问题描述】:
我有以下情况:
- 开始交易
- 获取对象 A
- 更新 A
- 提交事务
- 与 A 一起执行一项长期任务
- 更新 A(事务中不需要,但会很好)
如何做到这一点?我不想在第 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);
}
【问题讨论】:
-
经过您的编辑,现在
executeJob(job);和finishJob(job);是不同的交易,那么您现在有什么问题? -
为什么要用“@Transactional”注释类和单个方法。在类中添加“@Transactional”意味着它适用于每个方法。
-
在班级级别,您需要有
@EnableTransactionManagement注释。 -
我在这篇文章中添加了一些信息。 @UeliHofstetter 没有
@Transaction在类上我有“javax.persistence.TransactionRequiredException:没有事务正在进行中”。 @hagrawal 我的主班有@EnableTransactionManagement,所以我认为我不需要在单独的班级中使用它。 @hagrawal 我认为它应该以我想要的方式运行,但是在我测试它时,似乎不是。 -
用@Transactional 注释私有方法没有意义。 stackoverflow.com/questions/4396284/…(至少,在代理模式下)。您在此处拥有的唯一一个公共方法是
execute(),因此您可以对其进行注释,也可以对整个类进行注释。
标签: java spring hibernate jpa spring-transactions