春季JPA CRUD存储库在多线程环境中从数据库中获取旧数据



>我正在运行带有mysql数据库和kafka作为消息传递服务的spring启动应用程序(使用chainedKafkaTransactionManager为kafka和mysql进行事务同步(以进行一些异步操作。

当多条消息进入Kafka侦听器时,有时旧数据来自数据库,而不是以前提交的数据。

我正在使用crud存储库,而且这种情况仅同时发生在多条消息上

例: 更新一个具有名称和ID的对象PERSON;

第一条消息将按 id 获取对象并将名称更新为 SAM。

第二条消息将获取对象并将名称更新为 REGO

第三条消息将获取对象,然后如果我检查它包含 SAM 作为名称的数据,但在数据库中它具有 REGO。

我尝试将隔离属性添加为事务中提交的读取,但没有运气

// listeners  
@Autowired
private PersonRepository personRepository;
@Autowired
private AddressRepository addressRepository;     
@KafkaListener(id = "update_name", topics = "update_name")
@Transactional(readOnly = false)
public void updateName(PersonModel personModel) {
    Person person = personRepository.findById(personModel.getId());   
    log.info("before -> name which is in database : " + person.getName());
    person.setName(personModel.getName());
    person = personRepository.save(person);
    log.info("after-> name which is in database : " + person.getName());
}
@KafkaListener(id = "update_name_and_address", topics = "update_name_and_address")
@Transactional(readOnly = false)
public void updateNameAndAddress(PersonModel personModel) {
    Address addr= addressRepository.findById(personModel.getAddresId);    
    addr.setPlace(personModel.getPlace());
    addressRepository.save(addr);
    updateName(personModel);
}
// repository
public interface PersonRepository extends CrudRepository<Person , Integer> {
}

我需要数据库中的最新数据

当第三个事务在第二个事务提交之前启动时,就会发生这种情况。效果变得更加明显,因为 JPA 在会话中加载实体后不会重新加载实体。

为了尽量减少这个问题,请尽可能缩短您的交易时间。还要确保可能通过在新事务中重试来处理乐观锁定异常。

最新更新