繁体   English   中英

跨微服务的事务

[英]Transactions Across Microservices

我有两个实体:

实体A:

private Long idA;

实体B:

private Long idB;
private Long fkA;

我的微服务只能保存、修改或删除 B 实体:

存储库:

@Repository
public interface BRepository extends CrudRepository<B, Long>{

}

Feign 外部服务:

@FeignClient(value = "aExtClient", url = "${A_EXT_MS_URL}")
public interface AExtRemoteService {

    @DeleteMapping(path = "/a/{idA}", produces = MediaType.APPLICATION_JSON_VALUE)
    public Esito deleteA(@PathVariable(name = "idA") Long idA);

}

服务实现:

@Component
@Transactional(rollbackFor = BusinessServiceException.class)
public class BServiceImpl implements BService { 
    
    @Autowired
    private BRepository bRepository;
    
    @Autowired
    private AExtRemoteService aExtRemoteService;
    
    @Override
    public void deleteB(B b) {        
        
        Long idA = b.getFkA();
        
        bRepository.delete(b); //marker
        
        if(idA  != null) {
            aExtRemoteService.deleteA(idA);
        }
    }
    
}

外部服务只能保存、修改或删除 A 实体:

控制器:

@RestController
@RequestMapping("/a")
@CrossOrigin(origins = "${mocks.allowedCrossOrigins:*}")
public class AServiceMockController {

    @Autowired
    private AMockService aMockService;
    
    @DeleteMapping(value = {
            "/{idA}" }, produces = MediaType.APPLICATION_JSON_VALUE)
    public @ResponseBody ResponseEntity<Result> deleteA(@PathVariable(name = "idA") Long idA) {
        Result result = new Result();
        aMockService.deleteA(idA);
        result.setResult(true);
        result.setCod(String.valueOf(HttpStatus.OK.value()));
        result.setMess(HttpStatus.OK.name());
        return new ResponseEntity<>(result, HttpStatus.OK);
    }

}

服务:

@Service
public class AMockService {

    private final ARepository aRepository;    

    @Autowired
    public AMockService(ARepository aRepository) {
        this.aRepository = aRepository;
    }
    
    public void deleteA(Long idA) {
        A byId = aRepository.findById(idA).orElseThrow(NoSuchElementException);
        aRepository.delete(byId);
    }

}

存储库:

@Repository
public interface ARepository extends CrudRepository<A, Long>{

}

在调用 deleteB 时,外部服务已返回此消息:

Caused by: java.sql.SQLIntegrityConstraintViolationException: ORA-02292:  integrity constraint violated (X.YY) - child record found

我该如何解决? 似乎没有考虑到 bRepository.delete(b);

PS我可以访问外部服务,所以如果需要我可以修改它。

错误消息表明删除尚未完成。 我会尝试的第一件事是删除后手动 bRepository.flush()。

您可以在此处阅读有关刷新的信息: https : //www.baeldung.com/spring-data-jpa-save-saveandflush

您不能跨微服务进行这样的事务 - 一个是因为您正在使用对服务 A 的远程 http 调用,并且它本质上无法参与您在服务 B 中启动的事务。您正在使用的事务是资源本地事务 其次,您在服务中共享一个数据库,而远程 http 服务正试图删除一条具有外键关系作为父项的记录。 由于您使用的是 Spring 事务管理器,因此您可以使用事务事件侦听器在 B 中的事务成功完成后调用删除 A。 还有其他模式可以解决跨微服务的事务,例如Saga

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM