최근에 접한 시나리오는 @Async 주석으로 표시된 메서드 B가 @Transactional로 주석이 달린 메서드 A에서 호출되는 것이었습니다. 메서드 B가 실행될 때 메서드 A의 트랜잭션이 커밋되지 않았지만 메서드 B가 실행 중이었기 때문입니다. 메소드 A에서 제출되지 않은 데이터를 얻을 수 없으므로 결국 메소드 B가 비정상적으로 실행됩니다.
@Transactional public void create(User user){ // 如果用户已存在,则先删除 delete(user.id); // 创建用户 int userId = insert(user); // 更新用户信息 update(userId); } @Async public void update(Integer userId){ Icon icon = getUserIcon(userId); // 更新用户图片 updateUserPohot(userId,icon); }
위 코드와 마찬가지로 사용자 생성 메소드에 @Transactional 트랜잭션 주석을 표시한 후 그 안에 update() 업데이트 메소드를 호출했습니다. 이 메소드에는 @Async 주석이 표시되어 있습니다. 코드에는 문제가 없는 것처럼 보이지만 실제로 update() 메서드가 실행될 때는 다른 스레드에 의해 실행되기 때문에 create() 메서드에 해당하는 트랜잭션이 아직 제출되지 않았고 update( ) 메서드가 새로 삽입된 사용자 레코드를 읽을 수 없어 업데이트가 실패합니다.
로직을 조정하여 비동기 메서드를 호출하기 전에 트랜잭션이 커밋되었는지 확인하세요
이 문제의 원인은 @Transactional 및 @Async 주석을 함께 사용하기 때문입니다. 그런 다음 먼저 이 방향에서 시작할 수 있습니다. create() 메소드의 트랜잭션을 제출한 후 비동기 업데이트 메소드를 실행합니다.
public void create(User user){ int userId = doCreate(user); // 更新用户信息 update(userId); } @Transactional public void doCreate(User user){ // 如果用户已存在,则先删除 delete(user.id); // 创建用户 return insert(user); } @Async public void update(Integer userId){ Icon icon = getUserIcon(userId); // 更新用户图片 updateUserPohot(userId,icon); }
비동기 메소드는 트랜잭션 메소드 외부에서 호출되므로 비동기 메소드는 제출된 트랜잭션 데이터를 읽을 수 있습니다.
TransactionTemplate을 사용하여 @Transactional 주석을 대체할 수 있습니다
@Autowired TransactionTemplate transactionTemplate; public void create(User user){ int userId = transactionTemplate.execute(status->{ // 如果用户已存在,则先删除 delete(user.id); // 创建用户 return insert(user); }); // 更新用户信息 update(userId); } @Async public void update(Integer userId){ Icon icon = getUserIcon(userId); // 更新用户图片 updateUserPohot(userId,icon); }
TransactionTemplate을 사용하여 트랜잭션 세분성을 세분화하여 비동기 메서드를 호출하기 전에 트랜잭션이 커밋되었는지 확인하세요.
위의 솔루션은 기본적으로 문제를 해결할 수 있습니다. 다음은 인터넷에서 찾은 spring이 제공하는 솔루션입니다.
@Transactional public void create(User user){ // 如果用户已存在,则先删除 delete(user.id); // 创建用户 int userId = insert(user); TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronization() { @Override public void afterCommit() { // 更新用户信息 update(userId); } }); } @Async public void update(Integer userId){ Icon icon = getUserIcon(userId); // 更新用户图片 updateUserPohot(userId,icon); }
트랜잭션이 제출된 후 비동기 메서드를 작업으로 등록하면 Spring이 트랜잭션이 완료된 후 자동으로 도움을 줄 수 있습니다. 제출된 해당 작업을 수행합니다.
위 내용은 트랜잭션과 함께 SpringBoot를 비동기적으로 사용하는 문제를 해결하는 방법의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!