Oracle
 sql >> база данни >  >> RDS >> Oracle

Върнете обратно A, ако B се обърка. пружинно зареждане, jdbctemplate

@Transactional анотацията в spring работи, като обвива вашия обект в прокси, който от своя страна обвива методи, анотирани с @Transactional в сделка. Поради тази анотация няма да работи върху частни методи (както във вашия пример), тъй като частните методи не могат да бъдат наследени => те не могат да бъдат обвити (това не е вярно, ако използвате декларативни транзакции с aspectj, тогава свързаните с прокси предупреждения по-долу не важат).

Ето основно обяснение как @Transactional пролетната магия работи.

Вие написахте:

class A {
    @Transactional
    public void method() {
    }
}

Но това всъщност получавате, когато инжектирате боб:

class ProxiedA extends A {
   private final A a;

   public ProxiedA(A a) {
       this.a = a;
   }

   @Override
   public void method() {
       try {
           // open transaction ...
           a.method();
           // commit transaction
       } catch (RuntimeException e) {
           // rollback transaction
       } catch (Exception e) {
           // commit transaction
       }
   }
} 

Това има ограничения. Те не работят с @PostConstruct методи, защото се извикват преди обектът да бъде проксиран. И дори ако сте конфигурирали всичко правилно, транзакциите се връщат обратно само при без отметка изключения по подразбиране. Използвайте @Transactional(rollbackFor={CustomCheckedException.class}) ако имате нужда от връщане назад на някакво проверено изключение.

Друго често срещано предупреждение, което знам:

@Transactional методът ще работи само ако го извикате "отвън", в следващия пример b() няма да бъде обвит в транзакция:

class X {
   public void a() {
      b();
   }

   @Transactional
   public void b() {
   }
}

Това е също така, защото @Transactional работи чрез прокси на вашия обект. В примера по-горе a() ще извика X.b() не е подобрен метод "прокси прокси" b() така че няма да има транзакция. Като заобиколно решение трябва да извикате b() от друг боб.

Когато срещнете някое от тези предупреждения и не можете да използвате предложено решение (направете метода нечастен или извикайте b() от друг bean) можете да използвате TransactionTemplate вместо декларативни транзакции:

public class A {
    @Autowired
    TransactionTemplate transactionTemplate;

    public void method() {
        transactionTemplate.execute(status -> {
            A();
            B();
            return null;
        });
    }

...
} 

Актуализиране

Отговаряне на актуализиран въпрос от ОП с помощта на информация по-горе.

Кой метод трябва да бъде анотиран с @Transactional:changes()? databaseChanges()?

@Transactional(rollbackFor={Exception.class})
public void changes() throws Exception {
    someLogicBefore();
    databaseChanges();
    someLogicAfter();
}

Уверете се, че changes() се нарича "отвън" на бийн, а не от самия клас и след инстанцирането на контекста (напр. това не е afterPropertiesSet() или @PostConstruct анотиран метод). Разберете, че пружинното връщане на транзакцията само за непроверени изключения по подразбиране (опитайте се да бъдете по-конкретни в списъка с rollbackFor проверени изключения).



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Разбиране на Lob сегменти (SYS_LOB) в oracle?

  2. Най-бързият начин да проверите дали някои записи в таблицата на базата данни?

  3. Задаване на изчакване на мрежата за JDBC връзка

  4. Заключване на Liquibase - причини?

  5. къде трябва да сложа ресурси на инсталационната програма (wxs файл, dmg-script, икона) и как да конфигурирам maven antrun при внедряване на самостоятелно приложение