spring jpa crud存储库在多线程环境中从数据库中获取旧数据

时间:2019-07-10 15:55:17

标签: java spring-boot spring-data-jpa spring-kafka

我正在运行带有MySQL数据库和kafka作为消息传递服务的Spring Boot应用程序(使用用于kafka和mysql的chainedKafkaTransactionManager进行了事务同步)以进行一些异步操作。

当多条消息有时会发送给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> {

}

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

1 个答案:

答案 0 :(得分:1)

这种情况发生在第三笔交易在第二笔交易提交之前开始的时候。 效果变得更加明显,因为一旦在会话中加载了JPA,JPA不会重新加载它。

为了最小化此问题,请使您的交易越短越好。 还要确保您可以通过在新事务中重试来处理乐观的锁定异常。