Удаление записи с последующим выбором в той же самой Spring Transaction возвращает удаленную запись - PullRequest
0 голосов
/ 10 января 2019

У меня есть некоторый код в весенней транзакции с уровнем изоляции, установленным в SERIALIZABLE. Этот код делает несколько вещей: во-первых, он удаляет все записи из таблицы с установленным флагом, затем он выполняет выборку, чтобы гарантировать, что недопустимые записи не могут быть записаны, и, наконец, новые записи записываются.

Проблема в том, что селектор продолжает возвращать записи, которые были удалены, если код выполняется с аннотацией транзакции. Насколько я понимаю, поскольку мы выполняем эти операции в рамках той же самой весенней транзакции, что предыдущая операция удаления будет учитываться при выполнении операции выбора.

Мы используем Spring Boot 2.1 и Hibernate 5.2

Краткое описание кода приведено ниже:

@HystrixCommand
public void deleteRecord(EntityObj entityObj) {
    fooRepository.deleteById(entityObj.getId());
    //Below line added as part of debugging but I don't think I should really need it?
    fooRepository.flush();
}


public List<EntityObj> findRecordByProperty(final String property) {
    return fooRepository.findEntityObjByProperty(property);
}

@Transactional(isolation = Isolation.SERIALIZABLE)
public void debugReadWrite() {

    EntitiyObject entitiyObject = new EntityObject();
    entitiyObject.setId(1);
    deleteRecord(entitiyObject);
    List<EntityObj> results = findRecordByProperty("bar");
    if (!results.isEmpty()) {
        throw new RuntimeException("Should be no results!")
    }
}

Ответы [ 2 ]

0 голосов
/ 20 января 2019

Оказывается, проблема была в том, что мы использовали Hystrix. Транзакция начинается за пределами Hystirx, а затем проходит через команду Hystrix. Команда Hystrix использует пул потоков, поэтому транзакция теряется при выполнении в новом потоке из пула потоков Hystrix. Смотрите этот вопрос GitHub для получения дополнительной информации: https://github.com/spring-cloud/spring-cloud-netflix/issues/1381

0 голосов
/ 10 января 2019

Транзакция еще не зафиксирована, вам нужно завершить транзакцию и затем найти запись.

украшение deleteRecord с распространением = Propagation.REQUIRES_NEW) должно решить проблему

@Transactional(propagation = Propagation.REQUIRES_NEW)
public void deleteRecord(EntityObj entityObj) {
    fooRepository.deleteById(entityObj.getId());
    // flush not needed fooRepository.flush();
}

Сброс не требуется, потому что после удаления deleteRecord перевод будет зафиксирован.

под капотом

//start transaction
public void deleteRecord(EntityObj entityObj) {

    fooRepository.deleteById(entityObj.getId());

}
//commit transaction
...