1) Получить подтвержденное значение для другого потока с помощью @Transactional, 2) Откатить все транзакции на исключение для 4 различных служб - PullRequest
1 голос
/ 03 апреля 2019

У меня есть 2 проблемы, связанные друг с другом.Я использую Spring boot JPA.

Проблема - 1

Мне нужно совершить 4 разных сервиса.И я вызываю эти услуги по очереди на уровне контроллера.Сбой на любом сервисе должен откатить другую совершенную транзакцию.Например, если вызов метода Controller для потока 1 и, i) транзакция службы 1 выполнена успешно ii) транзакция службы 2 выполнена успешно iii) если транзакция службы 3 завершилась неудачей - тогда транзакция службы 1 и службы 2 должна выполнить откат

Проблема - 2

Я обновляю уникальное значение столбца в Сервисе-1.Кто первым читает объект, получает значение последней строки, увеличивает его, а затем снова сохраняет.Но когда другой поток вызывает тот же процесс, он читает ту же сущность, что и ранее, и возникает ошибка для повторяющегося значения.Например,

вызов Thread-1 Service-1 1) Считывание объекта для thread-1 2) Получение значения let скажем - 100 3) Увеличение значения до - 101 4) Сохранение объекта 5) Теперь вызов другого потокатот же сервис

вызов Thread-2 Service-1 1) чтение объекта для thread-2 2) получение значения - 100 вместо 101 выдает ошибку, поскольку после сохранения объекта для Thread-1 следует прочитать обновленное значениет.е. 101 для нити-2.но в настоящее время я получаю незафиксированное значение.

Я загружаю код здесь для уровня сущности, контроллера, сервиса и репозитория.

//Entity Level

@Entity
@Data
public class MyEntity {

    private Long id;

    @Column(unique = true)
    private Long uniqueCode;
}

@Entity
@Data
public class MyOtherEntity{
    private Long id;
}

//Repository Level

@Repository
public interface MyEntityRepository extends JpaRepository<MyEntity, Long> {
    MyEntity findFirstByOrderByIdDesc();
}

@Repository
public interface MyOtherEntityRepository extends JpaRepository<MyOtherEntity, Long> {
}


//Controller Level

@Controller
public class MyController {

    @Autowired
    private MyService myService;


    @PostMapping("/updateData")
    @ResponseBody
    public String updateData(){

        myService.updateDataForEntity();

        myService.updateDataForOtherEntity();

        myService.myThirdServiceCall();

        myService.myFourthServiceCall();

        return "success";
    }
}


//Service Level

@Service
public class MyService{

    @Autowired
    MyEntityRepository myEntityRepository;

    @Autowired
    MyOtherEntityRepository myOtherEntityRepository;

    @Synchronized // Using to prevent other thread call, however error occurs
    @Transactional // I have used previously (isolation = Isolation.SERIALIZABLE), but not get any result
    public void updateDataForEntity() {
        try {
            //Get last unique code value - HERE I GOT SAME VALUE FOR OTHER THREAD (T-2) THOUGH THREAD-1 WAS SAVED 
            MyEntity oldEntity = myEntityRepository.findFirstByOrderByIdDesc();

            //Set updated unique code value and save
            MyEntity newEntity = new MyEntity();
            newEntity.setUniqueCode(oldEntity.getUniqueCode() + 1L);
            myEntityRepository.save(newEntity);
        } catch (Exception e) {
            //Should Rollback
        }
    }

    public void updateDataForOtherEntity() {
        try {
            MyOtherEntity myOtherEntity = new MyOtherEntity();
            myOtherEntityRepository.save(myOtherEntity);
        } catch (Exception e) {
            //Must rollback on exception for Service-1
        }
    }

    public void myThirdServiceCall() {
        try {

        } catch (Exception e) {
            // Must rollback on exception for Service-2 and service-1 call
        }
    }

    public void myFourthServiceCall() {
        try {
        } catch (Exception e) {
            // Must rollback on exception for Third Service Call, Service-2 and service-1 call
        }
    }
}

Я прочитал учебник по уровню распространения транзакции и уровню изоляции,Но, пожалуйста, объясните мне, каким методом я могу использовать @Transactional для решения обеих проблем, как описано выше.

...