| | 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 операција и сите промени трајно се зачувуваат во базата на податоци. |