У меня есть 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 для решения обеих проблем, как описано выше.