[SPRING] 완성 가능한 미래 대 봄 거래
SPRING완성 가능한 미래 대 봄 거래
생각
처리 방법은 항목 목록을 가져 와서 외부 웹 서비스를 사용하여 비동기 적으로 처리하는 처리 방법입니다. 프로세스 단계는 또한 처리하는 동안 데이터를 유지합니다. 전체 프로세스가 끝나면 전체 프로세스를 각 처리 된 결과와 함께 유지하기를 원합니다.
문제
목록의 각 항목을 CompletableFuture로 변환하고 처리 작업을 실행하여 미래의 배열로 되돌립니다. 이제 제출 된 모든 작업이 완료 될 때 미래를 완료하고 그 결과를 보유하는 다른 CompletableFuture를 반환하는 .ofAll 메서드 (시퀀스 메서드)를 사용합니다.
그 결과를 얻으 려 할 때 .whenComplete (..)를 호출하고 반환 된 결과를 데이터로 내 엔터티에 설정 한 다음 데이터베이스에 유지하려고하지만 리포지토리 저장 호출은 아무 것도하지 않고 스레드 만 계속 처리합니다. 계속 실행하면 저장소 저장 호출을 지나치지 않습니다.
@Transactional
public void process(List<Item> items) {
List<Item> savedItems = itemRepository.save(items);
final Process process = createNewProcess();
final List<CompletableFuture<ProcessData>> futures = savedItems.stream()
.map(item -> CompletableFuture.supplyAsync(() -> doProcess(item, process), executor))
.collect(Collectors.toList());
sequence(futures).whenComplete((data, throwable) -> {
process.setData(data);
processRepository.save(process); // <-- transaction lost?
log.debug("Process DONE"); // <-- never reached
});
}
시퀀스 방법
private static <T> CompletableFuture<List<T>> sequence(List<CompletableFuture<T>> futures) {
CompletableFuture<Void> allDoneFuture =
CompletableFuture.allOf(futures.toArray(new CompletableFuture[futures.size()]));
return allDoneFuture.thenApply(v ->
futures.stream().map(CompletableFuture::join).collect(Collectors.toList())
);
}
무슨 일 이니? 지속 호출이 전달되지 않는 이유는 무엇입니까? 트랜잭션을 시작한 스레드가 트랜잭션을 커밋 할 수 없거나 손실 된 위치는 어디입니까? 모든 처리 된 데이터가 정상적으로 반환되며 모두 양호합니다. 다른 거래 전략을 시도했지만 트랜잭션이 완료 될 때 어떤 스레드가 트랜잭션을 완료 할지를 제어하는 것이 어떻게 가능합니까?
어떤 충고?
해결법
-
==============================
1.위와 같이 문제가 발생한 이유는 트랜잭션이 종료된다는 것입니다. 메소드 반환 과정 (..)에 도달했을 때.
위와 같이 문제가 발생한 이유는 트랜잭션이 종료된다는 것입니다. 메소드 반환 과정 (..)에 도달했을 때.
할 수있는 일은 수동으로 트랜잭션을 생성하는 것입니다. 시작과 끝 시간을 제어하십시오.
@ Transactional 삭제
프로세스 (..)에서 TransactionManager를 Autowire하십시오.
TransactionDefinition txDef = new DefaultTransactionDefinition(); TransactionStatus txStatus = transactionManager.getTransaction(txDef); try { //do your stuff here like doWhateverAsync().then(transactionManager.commit(txStatus);) } catch (Exception e) { transactionManager.rollback(txStatus); throw e; }
-
==============================
2.Spring Boot Application의 경우 다음과 같은 설정이 필요합니다.
Spring Boot Application의 경우 다음과 같은 설정이 필요합니다.
주요 응용 프로그램 메서드에는 @EnableAsync 주석이 있어야합니다.
@Async 어노테이션은 @Transactional 어노테이션이있는 메소드의 맨 위에 있어야합니다. 이것은 자식 스레드에서 처리가 수행됨을 나타 내기 위해 필요합니다.
from https://stackoverflow.com/questions/35628764/completablefuture-vs-spring-transactions by cc-by-sa and MIT license
'SPRING' 카테고리의 다른 글
[SPRING] Spring 데이터 소스 및 데이터베이스 스키마 (0) | 2019.05.11 |
---|---|
[SPRING] Appender 클래스 로깅에서 Spring 빈 액세스 (0) | 2019.05.11 |
[SPRING] Excel 스프레드 시트를 javax.sql.DataSource로 어떻게 구성 할 수 있습니까? (0) | 2019.05.11 |
[SPRING] jar 파일에서 실행하려고 할 때 스프링 부팅 응용 프로그램이 실행되지 않습니다. (0) | 2019.05.11 |
[SPRING] Tomcat이 war 파일에서 jsp를 찾을 수 없습니다. (0) | 2019.05.11 |