是否应将托管实体传递给需要新事务的方法?
我的应用程序加载应处理的实体列表。这发生在使用调度程序的类中
@Component
class TaskScheduler {
@Autowired
private TaskRepository taskRepository;
@Autowired
private HandlingService handlingService;
@Scheduled(fixedRate = 15000)
@Transactional
public void triggerTransactionStatusChangeHandling() {
taskRepository.findByStatus(Status.OPEN).stream()
.forEach(handlingService::handle);
}
}
在我的流程中,每个任务都在使用传播级别。HandlingService
REQUIRES_NEW
@Component
class HandlingService {
@Transactional(propagation = Propagation.REQUIRES_NEW)
public void handle(Task task) {
try {
processTask(task); // here the actual processing would take place
task.setStatus(Status.PROCCESED);
} catch (RuntimeException e) {
task.setStatus(Status.ERROR);
}
}
}
代码之所以有效,只是因为我在类上启动了父事务。如果我删除注释,则不再管理实体,并且对任务实体的更新不会传播到数据库。我发现使计划方法成为事务性方法并不自然。TaskScheduler
@Transactional
从我所看到的,我有两个选择:
1. 保持代码不变。
- 也许这只是我,这是一个正确的aproach。
- 此变体具有最少的数据库访问次数。
2. 从计划程序中删除@Transactional
注释,传递任务的 ID,然后在 HandlingService 中重新加载任务实体。
@Component
class HandlingService {
@Autowired
private TaskRepository taskRepository;
@Transactional(propagation = Propagation.REQUIRES_NEW)
public void handle(Long taskId) {
Task task = taskRepository.findOne(taskId);
try {
processTask(task); // here the actual processing would take place
task.setStatus(Status.PROCCESED);
} catch (RuntimeException e) {
task.setStatus(Status.ERROR);
}
}
}
- 具有更多数据库行程(一个额外的查询/元素)
- 可以使用以下命令执行
@Async
你能不能就哪种是解决这类问题的正确方法发表意见,也许用另一种我不知道的方法?