MS Lesson15: Transaction propogation
1. A servisi transactional metodu var ve B servisindeki non transactional metodu cagiri:
package guru.springframework.cruddemo.controller;
import guru.springframework.cruddemo.service.impl.AccountServiceImpl;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@Slf4j
@RequiredArgsConstructor
public class AccountController {
private final AccountServiceImpl accountServiceImpl;
@PostMapping("/transfer")
public void transfer() {
accountServiceImpl.transfer(30);
}
}
package guru.springframework.cruddemo.service.impl;
import guru.springframework.cruddemo.entity.Account;
import guru.springframework.cruddemo.repository.AccountRepository;
import guru.springframework.cruddemo.service.AccountService;
import guru.springframework.cruddemo.service.TxProxyDemoService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
@Service
@Slf4j
@RequiredArgsConstructor
public class AccountServiceImpl implements AccountService {
private final AccountRepository accountRepository;
private final TxProxyDemoService txProxyDemoService;
@Override
@Transactional(propagation = Propagation.REQUIRED)
public void transfer(Integer amount) {
System.out.println(Thread.currentThread().getName());
Account fromAccount = accountRepository.findById(1L).get();
Account toAccount = accountRepository.findById(2L).get();
fromAccount.setAmount(fromAccount.getAmount() - amount);
toAccount.setAmount(toAccount.getAmount() + amount);
txProxyDemoService.test();
}
private void foo() {
throw new RuntimeException("---------> xeta");
}
}
package guru.springframework.cruddemo.service.impl;
import guru.springframework.cruddemo.entity.TxProxyDemo;
import guru.springframework.cruddemo.repository.TxProxyDemoRepository;
import guru.springframework.cruddemo.service.TxProxyDemoService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
@Slf4j
@Service
@RequiredArgsConstructor
public class TxProxyDemoServiceImpl implements TxProxyDemoService {
private final TxProxyDemoRepository repository;
@Override
// @Transactional
public void test() {
System.out.println(Thread.currentThread().getName());
TxProxyDemo txProxyDemo = repository.findById(1L).get();
txProxyDemo.setContent("demo");
foo();
}
private void foo() {
throw new RuntimeException("------> Something went wrong");
}
}
Bu zaman transaction B servisindeki metoda da oturulur, orada davam edir ve tranzaksiya A servisindeki metodda bitir.
2. Required - bu @Transactional yazanda default secimdir.
A servisindeki @Transactional metoddan B servisindeki @Transactional metodu cagirirsa B servisindeki tranzaksiya yeni tranzaksiya acmir A ni davam eletdirir, yeni A nin tranzaksiyasi B ye oturulur.
Bu zaman her hansisa bir metodda Runtime exception bash verersen bu tranzaksiya vahid bir tranzaksiya kimi davranacaq ve butun emeliyyat (hem A hem B) rollback olacaq.
3. Requires_new - bu zaman yeni tranzaksiya serhedi teyin olunur. Bunu gormek ucun:
System.out.println(TransactionSynchronizationManager.getCurrentTransactionName());
Qisa qayda: Requires_new neye gore var? Birincide xeta bash verse ikinciye tesir etmesin, bu qeder sade.
4. Supports - tranzaksiya varsa qatil, yoxdursa tranzaksiyasiz ishle.
Qisa qayda: yazsanda yazmasanda ferq etmir.
5. Not_supported - tranzaksiya varsa suspend et, tranzaksiya olmadan ishle.
package guru.springframework.cruddemo.service.impl;
import guru.springframework.cruddemo.entity.Account;
import guru.springframework.cruddemo.repository.AccountRepository;
import guru.springframework.cruddemo.service.AccountService;
import guru.springframework.cruddemo.service.TxProxyDemoService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.support.TransactionSynchronizationManager;
@Service
@Slf4j
@RequiredArgsConstructor
public class AccountServiceImpl implements AccountService {
private final AccountRepository accountRepository;
private final TxProxyDemoService txProxyDemoService;
@Override
@Transactional(propagation = Propagation.REQUIRED)
public void transfer(Integer amount) {
System.out.println(Thread.currentThread().getName());
System.out.println(TransactionSynchronizationManager.getCurrentTransactionName());
Account fromAccount = accountRepository.findById(1L).get();
Account toAccount = accountRepository.findById(2L).get();
fromAccount.setAmount(fromAccount.getAmount() - amount);
toAccount.setAmount(toAccount.getAmount() + amount);
txProxyDemoService.test();
// foo();
}
private void foo() {
throw new RuntimeException("---------> xeta");
}
}
package guru.springframework.cruddemo.service.impl;
import guru.springframework.cruddemo.entity.TxProxyDemo;
import guru.springframework.cruddemo.repository.TxProxyDemoRepository;
import guru.springframework.cruddemo.service.TxProxyDemoService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.support.TransactionSynchronizationManager;
@Slf4j
@Service
@RequiredArgsConstructor
public class TxProxyDemoServiceImpl implements TxProxyDemoService {
private final TxProxyDemoRepository repository;
@Override
@Transactional(propagation = Propagation.NOT_SUPPORTED)
public void test() {
System.out.println(Thread.currentThread().getName());
System.out.println(TransactionSynchronizationManager.getCurrentTransactionName());
TxProxyDemo txProxyDemo = repository.findById(1L).get();
txProxyDemo.setContent("demo");
// repository.save(txProxyDemo);
// foo();
}
private void foo() {
throw new RuntimeException("------> Something went wrong");
}
}
test() metodunda RuntimeException bash verse bu exceptionu cagirildigi metode yoneldecek.
Ne zaman lazim ola biler: cox vaxt uzun ve ya yavash ishleyen ishler (mes. email, HTTP fayl, agir hesabat) ve ya bu addim aktiv DB transaction-da olmasin dediyimiz hallarda - esas transaction-u suspend edib hemin hisseni tx-siz ishletmek ucun.
6. Mandatory - mutleq aktiv tranzaksiya olmalidir, eks halda xeta atilacaq. open-in-view = true buna hec bir tesiri yoxdur, yalniz session aciq saxlayir, response controllere qayitdiqdan sonra session baglanir.
7. Never - hec vaxt tranzaksiya olmamalidir, varsa xeta atsin. Tranzaksiya yoxdursa normal tranzaksiyasiz (adi metod kimi) ishleyir.
8. Nested - daxili nested savepoint (JDBC savepoint; DataSource desteklemelidir). Spring-in yeni versiyasinda desteklemir, evezine : Required_new + try/catch bloku. Yeni B-de xeta olsa bele, A davam etsin.
Комментарии
Отправить комментарий