| 1 | = Трансакции |
| 2 | |
| 3 | == Трансакција за креирање на изнајмување |
| 4 | |
| 5 | {{{ |
| 6 | @Transactional(rollbackFor = Exception.class, isolation = Isolation.READ_COMMITTED) |
| 7 | public Lease save(Long listingId, |
| 8 | Long tenantId, |
| 9 | Long landlordUserId, |
| 10 | LocalDate startDate, |
| 11 | LocalDate endDate, |
| 12 | BigDecimal rentAmount, |
| 13 | BigDecimal depositAmount) { |
| 14 | try { |
| 15 | System.out.println("=== ЗАПОЧНУВАЊЕ НА ТРАНСАКЦИЈА ЗА КРЕИРАЊЕ НА ИЗНАЈМУВАЊЕ ==="); |
| 16 | Listing listing = listingService.findById(listingId); |
| 17 | |
| 18 | if (!"available".equals(listing.getStatus())) { |
| 19 | throw new IllegalStateException("Огласот не е достапен за изнајмување. Статус: " + listing.getStatus()); |
| 20 | } |
| 21 | |
| 22 | TenantProfile tenant = tenantProfileService.findByUserId(tenantId); |
| 23 | if (tenant == null) { |
| 24 | throw new IllegalArgumentException("Изнајмувачот не е пронајден со ID: " + tenantId); |
| 25 | } |
| 26 | |
| 27 | LandlordProfile landlord = landlordProfileService.findByUserId(landlordUserId); |
| 28 | if (landlord == null) { |
| 29 | throw new IllegalArgumentException("Издавачот не е пронајден со ID: " + landlordUserId); |
| 30 | } |
| 31 | |
| 32 | System.out.println("TENANT ID: " + tenant.getId()); |
| 33 | System.out.println("LANDLORD ID: " + landlord.getId()); |
| 34 | |
| 35 | Lease lease = new Lease( |
| 36 | startDate, |
| 37 | endDate, |
| 38 | rentAmount, |
| 39 | depositAmount, |
| 40 | listing, |
| 41 | tenant, |
| 42 | landlord |
| 43 | ); |
| 44 | |
| 45 | Lease savedLease = leaseRepository.save(lease); |
| 46 | listing.setStatus("rented"); |
| 47 | listingService.save(listing); |
| 48 | return savedLease; |
| 49 | |
| 50 | } catch (Exception e) { |
| 51 | System.err.println("ГРЕШКА ВО ТРАНСАКЦИЈАТА: " + e.getMessage()); |
| 52 | throw new RuntimeException("Грешка при креирање на изнајмување: " + e.getMessage(), e); |
| 53 | } |
| 54 | } |
| 55 | |
| 56 | }}} |
| 57 | Оваа трансакција вклучува повеќе операции во базата на податоци кои мора да се извршат како една целина. Методот save() е анотиран со |
| 58 | `@Transactional(rollbackFor = Exception.class, isolation = Isolation.READ_COMMITTED)` |
| 59 | што значи дека сите операции во рамките на методот се третираат како една атомска единица. |
| 60 | |
| 61 | Прво се проверува дали огласот постои и дали е достапен за изнајмување со статус "available". Доколку огласот не е достапен, се фрла исклучок кој автоматски ја прекинува трансакцијата и се извршува ROLLBACK. |
| 62 | |
| 63 | Потоа се бараат и валидираат профилите на издавач и изнајмувачот. Доколку било кој од нив не постои во базата, повторно се фрла исклучок и трансакцијата се поништува. Со ова се постигнува `CONSISTENCY`- се гарантира дека во базата нема да се внесат невалидни или неконзистентни податоци. |
| 64 | Кога сите валидации поминуваат успешно, се извршуваат две клучни операции во базата: |
| 65 | |
| 66 | - Прва операција: Се креира и зачувува изнајмување во табелата Lease |
| 67 | - Втора операција: Се ажурира статусот на огласот од "available" во "rented" и истиот се зачувува во базата. |
| 68 | |
| 69 | Овие две операции се атомски поврзани - или и двете ќе успеат, или и двете ќе се поништат. Не може да се случи ситуација каде изнајмувањето е креирано, а статусот на огласот не е ажуриран, или обратно. |
| 70 | |
| 71 | `ATOMICITY` се постигнува преку @Transactional анотацијата со параметар rollbackFor = Exception.class. Ова значи дека доколку се фрли било кој исклучок при извршување на методата, сите промени што се направени до тој момент автоматски се поништуваат со ROLLBACK операцијата. |
| 72 | |
| 73 | `ISOLATION` се постигнува преку параметарот isolation = Isolation.READ_COMMITTED кој спречува други паралелни трансакции да читаат неодобрени промени. На тој начин се гарантира дека два корисника истовремено нема да можат да креираат договор за истиот листинг. |
| 74 | |
| 75 | `DURABILITY` се постигнува автоматски кога методот завршува успешно без фрлање на исклучок. Во тој случај, Spring автоматски врши COMMIT операција и сите промени трајно се зачувуваат во базата на податоци. |