= Трансакции == Трансакција за креирање на изнајмување {{{ @Transactional(rollbackFor = Exception.class, isolation = Isolation.READ_COMMITTED) public Lease save(Long listingId, Long tenantId, Long landlordUserId, LocalDate startDate, LocalDate endDate, BigDecimal rentAmount, BigDecimal depositAmount) { try { System.out.println("=== ЗАПОЧНУВАЊЕ НА ТРАНСАКЦИЈА ЗА КРЕИРАЊЕ НА ИЗНАЈМУВАЊЕ ==="); Listing listing = listingService.findById(listingId); if (!"available".equals(listing.getStatus())) { throw new IllegalStateException("Огласот не е достапен за изнајмување. Статус: " + listing.getStatus()); } TenantProfile tenant = tenantProfileService.findByUserId(tenantId); if (tenant == null) { throw new IllegalArgumentException("Изнајмувачот не е пронајден со ID: " + tenantId); } LandlordProfile landlord = landlordProfileService.findByUserId(landlordUserId); if (landlord == null) { throw new IllegalArgumentException("Издавачот не е пронајден со ID: " + landlordUserId); } System.out.println("TENANT ID: " + tenant.getId()); System.out.println("LANDLORD ID: " + landlord.getId()); Lease lease = new Lease( startDate, endDate, rentAmount, depositAmount, listing, tenant, landlord ); Lease savedLease = leaseRepository.save(lease); listing.setStatus("rented"); listingService.save(listing); return savedLease; } catch (Exception e) { System.err.println("ГРЕШКА ВО ТРАНСАКЦИЈАТА: " + e.getMessage()); throw new RuntimeException("Грешка при креирање на изнајмување: " + e.getMessage(), e); } } }}} Оваа трансакција вклучува повеќе операции во базата на податоци кои мора да се извршат како една целина. Методот save() е анотиран со `@Transactional(rollbackFor = Exception.class, isolation = Isolation.READ_COMMITTED)` што значи дека сите операции во рамките на методот се третираат како една атомска единица. Прво се проверува дали огласот постои и дали е достапен за изнајмување со статус "available". Доколку огласот не е достапен, се фрла исклучок кој автоматски ја прекинува трансакцијата и се извршува ROLLBACK. Потоа се бараат и валидираат профилите на издавач и изнајмувачот. Доколку било кој од нив не постои во базата, повторно се фрла исклучок и трансакцијата се поништува. Со ова се постигнува `CONSISTENCY`- се гарантира дека во базата нема да се внесат невалидни или неконзистентни податоци. Кога сите валидации поминуваат успешно, се извршуваат две клучни операции во базата: - Прва операција: Се креира и зачувува изнајмување во табелата Lease - Втора операција: Се ажурира статусот на огласот од "available" во "rented" и истиот се зачувува во базата. Овие две операции се атомски поврзани - или и двете ќе успеат, или и двете ќе се поништат. Не може да се случи ситуација каде изнајмувањето е креирано, а статусот на огласот не е ажуриран, или обратно. `ATOMICITY` се постигнува преку @Transactional анотацијата со параметар rollbackFor = Exception.class. Ова значи дека доколку се фрли било кој исклучок при извршување на методата, сите промени што се направени до тој момент автоматски се поништуваат со ROLLBACK операцијата. `ISOLATION` се постигнува преку параметарот isolation = Isolation.READ_COMMITTED кој спречува други паралелни трансакции да читаат неодобрени промени. На тој начин се гарантира дека два корисника истовремено нема да можат да креираат договор за истиот листинг. `DURABILITY` се постигнува автоматски кога методот завршува успешно без фрлање на исклучок. Во тој случај, Spring автоматски врши COMMIT операција и сите промени трајно се зачувуваат во базата на податоци.